分布式系统开发实战:基于Spring Security实现安全认证

简介: 在本节,将演示基于Spring Security安全认证功能。该应用代码可以在security basic目录下找到。

在本节,将演示基于Spring Security安全认证功能。该应用代码可以在security basic目录下找到。

19.5.1 添加依赖

添加Spring Security的依赖时,由于是使用的snapshot版本,所以,要配置Spring Snapshots仓库。配置如下。

<!-- Spring Snapshots仓库 -->
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
</repository>
</repositories>
<properties>
<spring.version>5.1.5.RELEASE</spring.version>
<jetty.version>9.4.14.v20181114</jetty.version>
<jackson.version>2.9.7</jackson.version>
<spring-security.version>5.2.0.BUILD-SNAPSHOT</spring-security.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency><!-- 安全相关的依赖 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>
</dependencies>

19.5.2 添加业务代码

业务代码里面包含了模型和控制器。

1.User模型

User类代码如下。

package com.waylau.spring.mvc.vo;
public class User {
private String username;
private Integer age;
public User(String username, Integer age) {
this.username = username;
this.age = age;
}
//省略getter/setter方法
}

2.控制器

控制器HelloController代码如下。

package com.waylau.spring.mvc.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.waylau.spring.mvc.vo.User;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello World! Welcome to visit waylau.com!";}
@RequestMapping("/hello/way")
public User helloWay() {
return new User("Way Lau", 30);
}
}

上述控制器的逻辑非常简单,当访问“/hello”时,会响应一段文本;当访问“/hello/way”会返回一个POJO对象。

该POJO对象,可以根据消息转换器的设置,来生成不同格式的消息。

19.5.3 配置消息转换器

添加Spring Web MVC的配置类MvcConfiguration,并在该配置中启用消息转换器。

package com.waylau.spring.mvc.configuration;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc // 启用MVC
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
public void extendMessageConverters(List<HttpMessageConverter<?>> cs) {
// 使用Jackson JSON来进行消息转换
cs.add(new MappingJackson2HttpMessageConverter());
}
}

由于预先在pom.xml中添加了Jackson JSON的依赖,因此可以使用

Jackson JSON来进行消息转换,将响应消息体转为JSON格式。

19.5.4 配置Spring Security

以下是针对Spring Security的配置。

package com.waylau.spring.mvc.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAd
apter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@EnableWebSecurity // 启用Spring Security功能
public class WebSecurityConfig
extends WebSecurityConfigurerAdapter {
/**
* 自定义配置
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()//所有请求都需认证
.and()
.formLogin() // 使用form表单登录
.and()
.httpBasic(); // HTTP基本认证
}
@SuppressWarnings("deprecation")
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager =
new InMemoryUserDetailsManager();
manager.createUser(
User.withDefaultPasswordEncoder() // 密码编码器
.username("waylau") // 用户名
.password("123") // 密码
.roles("USER") // 角色
.build()
);
return manager;
}
}

在上述配置中,要启动Spring Security功能,需要在配置类上添加@EnableWebSecurity注解。

安全配置类WebSecurityConfig继承自


WebSecurityConfigurerAdapter。WebSecurity Configurer Adapter提供用于创建一个Websecurityconfigurer实例方便的基类,允许自定义重写其方法。这里,我们重写了configure方法:authorizeRequests().anyRequest().authenticated()方法意味着所有请求都需认证;formLogin()方法表明这是基于表单的身份验证;httpBasic()方法表明该认证是一个HTTP基本认证。

UserDetailsService用于提供身份认证信息。本例使用了基于内存的信息管理器InMemory UserDetailsManager,同时初始化了一个用户名为“waylau”、密码为“123”、角色为“USER”的身份信息。
withDefaultPasswordEncoder()方法指定了该用户身份信息使用默认的密码编码器。

19.5.5 创建应用配置类

AppConfiguration是整个应用的配置类,用于导入Spring Web MVC及Spring Security的配置信息。代码如下。

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@ComponentScan(basePackages = { "com.waylau.spring" })
@Import({ WebSecurityConfig.class, MvcConfiguration.class})
public class AppConfiguration {
}

19.5.6 创建内嵌Jetty的服务器

创建内嵌了Jetty的服务器,代码如下。

package com.waylau.spring.mvc;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;
import com.waylau.spring.mvc.configuration.AppConfiguration;
public class JettyServer {
private static final int DEFAULT_PORT = 8080;
private static final String CONTEXT_PATH = "/";
private static final String MAPPING_URL = "/*";
public void run() throws Exception {
Server server = new Server(DEFAULT_PORT);
server.setHandler(servletContextHandler(webApplicationContext()));
server.start();
server.join();
}
private ServletContextHandler servletContextHandler(WebApplicationContext ct) {
// 启用Session管理器
ServletContextHandler handler =
new ServletContextHandler(ServletContextHandler.SESSIONS);
handler.setContextPath(CONTEXT_PATH);
handler.addServlet(new ServletHolder(new DispatcherServlet(ct)),
MAPPING_URL);
handler.addEventListener(new ContextLoaderListener(ct));
// 添加Spring Security过滤器
FilterHolder filterHolder=new FilterHolder(DelegatingFilterProxy.class);
filterHolder.setName("springSecurityFilterChain");
handler.addFilter(filterHolder, MAPPING_URL,
EnumSet.of(DispatcherType.REQUEST));
return handler;
}
private WebApplicationContext webApplicationContext() {
AnnotationConfigWebApplicationContext context =
new AnnotationConfigWebApplicationContext();
context.register(AppConfiguration.class);
return context;
}
}

JettyServer将Spring的上下文Servlet、监听器、过滤器等信息都传给了Jetty服务。

19.5.7 应用启动器

创建应用启动类Application,代码如下。

package com.waylau.spring.mvc;
public class Application {
public static void main(String[] args) throws Exception {
new JettyServer().run();
}
}

19.5.8 运行应用

右键运行Application类即可启动应用。

访问
http://localhost:8080/hello/way,会跳转到登录界面,意味着被安全认证拦截了。正如WebSecurityConfig所配置的那样,登录界面是一个form表单,

尝试输入一个错误的用户名和密码,可以看到所示的错误提示信息。

用初始化好的用户名和密码进行成功登录,可以看到能够正常访问应用的API

19.6 本章小结

本章介绍了分布式系统安全性的基本概念、加密算法,同时也介绍了安全通道及访问控制。本章也演示了如何基于Spring Security框架来实现安全认证。

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

相关文章
|
5月前
|
人工智能 Kubernetes 数据可视化
Kubernetes下的分布式采集系统设计与实战:趋势监测失效引发的架构进化
本文回顾了一次关键词监测任务在容器集群中失效的全过程,分析了中转IP复用、调度节奏和异常处理等隐性风险,并提出通过解耦架构、动态IP分发和行为模拟优化采集策略,最终实现稳定高效的数据抓取与分析。
Kubernetes下的分布式采集系统设计与实战:趋势监测失效引发的架构进化
|
7月前
|
消息中间件 运维 Kafka
直播预告|Kafka+Flink双引擎实战:手把手带你搭建分布式实时分析平台!
在数字化转型中,企业亟需从海量数据中快速提取价值并转化为业务增长动力。5月15日19:00-21:00,阿里云三位技术专家将讲解Kafka与Flink的强强联合方案,帮助企业零门槛构建分布式实时分析平台。此组合广泛应用于实时风控、用户行为追踪等场景,具备高吞吐、弹性扩缩容及亚秒级响应优势。直播适合初学者、开发者和数据工程师,参与还有机会领取定制好礼!扫描海报二维码或点击链接预约直播:[https://developer.aliyun.com/live/255088](https://developer.aliyun.com/live/255088)
567 35
直播预告|Kafka+Flink双引擎实战:手把手带你搭建分布式实时分析平台!
|
2月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
7月前
|
消息中间件 运维 Kafka
直播预告|Kafka+Flink 双引擎实战:手把手带你搭建分布式实时分析平台!
直播预告|Kafka+Flink 双引擎实战:手把手带你搭建分布式实时分析平台!
235 12
|
9月前
|
数据采集 存储 数据可视化
分布式爬虫框架Scrapy-Redis实战指南
本文介绍如何使用Scrapy-Redis构建分布式爬虫系统,采集携程平台上热门城市的酒店价格与评价信息。通过代理IP、Cookie和User-Agent设置规避反爬策略,实现高效数据抓取。结合价格动态趋势分析,助力酒店业优化市场策略、提升服务质量。技术架构涵盖Scrapy-Redis核心调度、代理中间件及数据解析存储,提供完整的技术路线图与代码示例。
963 0
分布式爬虫框架Scrapy-Redis实战指南
|
8月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
297 5
|
3月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
258 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
5月前
|
数据采集 缓存 NoSQL
分布式新闻数据采集系统的同步效率优化实战
本文介绍了一个针对高频新闻站点的分布式爬虫系统优化方案。通过引入异步任务机制、本地缓存池、Redis pipeline 批量写入及身份池策略,系统采集效率提升近两倍,数据同步延迟显著降低,实现了分钟级热点追踪能力,为实时舆情监控与分析提供了高效、稳定的数据支持。
201 1
分布式新闻数据采集系统的同步效率优化实战
|
7月前
|
安全 JavaScript 前端开发
HarmonyOS NEXT~HarmonyOS 语言仓颉:下一代分布式开发语言的技术解析与应用实践
HarmonyOS语言仓颉是华为专为HarmonyOS生态系统设计的新型编程语言,旨在解决分布式环境下的开发挑战。它以“编码创造”为理念,具备分布式原生、高性能与高效率、安全可靠三大核心特性。仓颉语言通过内置分布式能力简化跨设备开发,提供统一的编程模型和开发体验。文章从语言基础、关键特性、开发实践及未来展望四个方面剖析其技术优势,助力开发者掌握这一新兴工具,构建全场景分布式应用。
747 35
|
6月前
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
1796 7

热门文章

最新文章