版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2026年SpringSecurity6.x权限控制实战与源码剖析
#2026年SpringSecurity6.x权限控制实战与源码剖析
##一、SpringSecurity6.x核心概念与架构概述
SpringSecurity是一款功能强大且高度可定制的安全框架,广泛应用于Java应用程序中,用于提供认证(Authentication)和授权(Authorization)功能。随着Spring框架的不断演进,SpringSecurity也在持续更新,SpringSecurity6.x版本在性能、易用性和扩展性方面进行了重大优化。本文将深入探讨SpringSecurity6.x的权限控制机制,并结合实战案例和源码剖析,帮助读者全面理解其工作原理。
###1.1SpringSecurity6.x的认证与授权流程
在深入探讨权限控制之前,我们需要先理解SpringSecurity的认证与授权流程。认证是指验证用户身份的过程,而授权则是确定用户是否有权访问特定资源的过程。SpringSecurity6.x的认证授权流程可以概括为以下几个关键步骤:
1.**请求拦截**:当用户发起请求时,SpringSecurity的过滤器链(FilterChain)会拦截该请求。默认情况下,SpringSecurity提供了多个内置过滤器,如`UsernamePasswordAuthenticationFilter`、`FilterSecurityInterceptor`等,这些过滤器负责处理不同的安全需求。
2.**认证尝试**:如果请求需要认证(例如,用户未登录或请求了受保护资源),`UsernamePasswordAuthenticationFilter`会尝试从请求中获取用户凭证(如用户名和密码),并将其传递给`AuthenticationManager`进行认证。
3.**AuthenticationManager处理**:`AuthenticationManager`是SpringSecurity的核心组件,负责实际的用户认证工作。默认情况下,`AuthenticationManager`会调用`UserDetailsService`加载用户信息,并验证用户凭证。如果认证成功,`AuthenticationManager`会返回一个`Authentication`对象,其中包含用户的详细信息。
4.**授权检查**:认证成功后,SpringSecurity会检查用户是否有权访问当前请求的资源。这一步骤由`FilterSecurityInterceptor`负责,它会根据配置的`SecurityExpressionHandler`评估安全表达式(如`hasRole("ADMIN")`),并决定是否允许用户访问资源。
5.**响应处理**:根据认证和授权的结果,SpringSecurity会决定如何响应请求。如果认证或授权失败,通常会返回401或403状态码;如果成功,则继续处理请求。
###1.2SpringSecurity6.x的核心组件
SpringSecurity6.x的架构主要由以下几个核心组件构成:
-**FilterChain**:过滤器链是SpringSecurity的核心,负责拦截和处理请求。SpringSecurity6.x提供了更灵活的过滤器链配置,允许开发者自定义过滤器顺序和逻辑。
-**AuthenticationManager**:认证管理器是负责用户认证的核心组件,它接收`Authentication`对象并返回认证结果。SpringSecurity6.x支持多种认证策略,如基于表单的认证、基于JWT的认证等。
-**UserDetailsService**:用户信息服务接口,用于加载用户详细信息。SpringSecurity6.x对`UserDetailsService`进行了优化,支持异步加载用户信息,提高了认证性能。
-**SecurityContextHolder**:安全持有者,用于存储当前认证用户的`Authentication`对象。SpringSecurity6.x对`SecurityContextHolder`进行了改进,支持线程本地存储,确保线程安全。
-**SecurityExpressionHandler**:安全表达式处理器,用于评估安全表达式(如`hasRole("ADMIN")`)。SpringSecurity6.x提供了更丰富的表达式支持,如方法调用、属性访问等。
-**AuthorizationManager**:授权管理器,用于检查用户是否有权访问特定资源。SpringSecurity6.x对`AuthorizationManager`进行了优化,支持更复杂的授权逻辑。
###1.3SpringSecurity6.x的配置方式
SpringSecurity6.x支持多种配置方式,包括注解配置、XML配置和Java配置。本文将以Java配置为例,展示如何配置SpringSecurity的权限控制。
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
importorg.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
privatefinalPasswordEncoderpasswordEncoder;
publicSecurityConfig(PasswordEncoderpasswordEncoder){
this.passwordEncoder=passwordEncoder;
}
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder.encode("admin"))
.roles("ADMIN");
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上面的配置中,我们定义了两个用户:`user`和`admin`。`user`具有`USER`角色,只能访问`/public/**`路径;`admin`具有`ADMIN`角色,可以访问`/public/**`和`/admin/**`路径。此外,我们还配置了表单登录和HTTP基本认证。
###1.4SpringSecurity6.x的安全表达式
SpringSecurity6.x提供了强大的安全表达式机制,允许开发者定义复杂的访问控制逻辑。安全表达式基于表达式语言(如SpEL),支持方法调用、属性访问、逻辑运算等。
.hasRole("ADMIN")
.hasAuthority("READ")
.hasAnyRole("USER","ADMIN")
.hasIpAddress("")
.hasAuthority("com.example.security.HasPermission")
在上面的表达式中:
-`hasRole("ADMIN")`:检查用户是否具有`ADMIN`角色。
-`hasAuthority("READ")`:检查用户是否具有`READ`权限。
-`hasAnyRole("USER","ADMIN")`:检查用户是否具有`USER`或`ADMIN`角色中的任意一个。
-`hasIpAddress("")`:检查用户的IP地址是否为``。
-`hasAuthority("com.example.security.HasPermission")`:检查用户是否具有自定义权限。
安全表达式可以在`HttpSecurity`配置中使用,例如:
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasAuthority("com.example.security.AdminAccess")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
在上面的配置中,`/admin/**`路径需要用户具有`com.example.security.AdminAccess`权限。
###1.5SpringSecurity6.x的实战案例
为了更好地理解SpringSecurity6.x的权限控制,我们来看一个实战案例:一个简单的RESTAPI,包含用户认证和授权功能。
####1.5.1项目结构
项目结构如下:
src
├──main
│├──java
││└──com
││└──example
││└──security
││├──SecurityConfig.java
││└──SecurityController.java
│├──resources
││└──perties
│└──webapp
│└──index.html
└──test
└──java
└──com
└──example
└──security
└──SecurityControllerTest.java
####1.5.2配置文件
`perties`:
spring.datasource.url=jdbc:mysql://localhost:3306/security
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
`SecurityConfig.java`:
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
privatefinalBCryptPasswordEncoderpasswordEncoder=newBCryptPasswordEncoder();
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.and()
.withUser("admin")
.password(passwordEncoder.encode("admin"))
.roles("ADMIN");
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
####1.5.3控制器
`SecurityController.java`:
importorg.springframework.security.access.prepost.PreAuthorize;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;
@RestController
publicclassSecurityController{
@GetMapping("/public/hello")
publicStringhelloPublic(){
return"Hello,public!";
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/hello")
publicStringhelloAdmin(){
return"Hello,admin!";
}
@PreAuthorize("hasAuthority('com.example.security.Read')")
@GetMapping("/read/hello")
publicStringhelloRead(){
return"Hello,read!";
}
}
在上面的控制器中:
-`/public/hello`:无需认证即可访问。
-`/admin/hello`:需要`ADMIN`角色才能访问。
-`/read/hello`:需要`com.example.security.Read`权限才能访问。
####1.5.4测试
`SecurityControllerTest.java`:
```java
importorg.junit.jupiter.api.Test;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.security.test.context.support.WithMockUser;
importorg.springframework.test.web.servlet.MockMvc;
importstaticorg.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
importstaticorg.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
importstaticorg.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
publicclassSecurityControllerTest{
@Autowired
privateMockMvcmockMvc;
@Test
publicvoidtestPublic()throwsException{
mockMvc.perform(get("/public/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello,public!"));
}
@Test
publicvoidtestAdmin()throwsException{
mockMvc.perform(get("/admin/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello,admin!"));
}
@Test
publicvoidtestRead()throwsException{
mockMvc.perform(get("/read/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello,read!"));
}
@Test
publicvoidtestAdminFail()throwsException{
mockMvc.perform(get("/admin/hello"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(username="user",roles="USER")
publicvoidtestReadFail()throwsException{
mockMvc.perform(get("/read/hello"))
.andExpect(status().isUnauthorized());
}
}
在上面的测试中:
-`testPublic`:测试公开路径。
-`testAdmin`:测试需要`ADMIN`角色的路径。
-`testRead`:测试需要`com.example.security.Read`权限的路径。
-`testAdminFail`:测试没有`ADMIN`角色的用户访问`/admin/hello`路径,预期返回401。
-`testReadFail`:测试没有`com.example.security.Read`权限的用户访问`/read/hello`路径,预期返回401。
##一、SpringSecurity6.x核心概念与架构概述(续)
###1.6SpringSecurity6.x与OAuth2的集成
SpringSecurity6.x提供了对OAuth2的全面支持,包括OAuth2客户端和资源服务器。开发者可以通过配置SpringSecurityOAuth2来轻松实现OAuth2认证和授权。
```java
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.authentication.AuthenticationManager;
importorg.springframework.security.oauth2.client.OAuth2ClientContext;
importorg.springframework.security.oauth2.client.OAuth2ClientEnvironment;
importorg.springframework.security.oauth2.client.config.annotation.web.configuration.EnableAuthorizationCodeResourceOwnerClientRegistries;
importorg.springframework.security.oauth2.client.config.annotation.web.configuration.EnableAuthorizationCodeResourceOwnerClientRegistry;
importorg.springframework.security.oauth2.client.config.annotation.web.configuration.EnableResourceServer;
importorg.springframework.security.oauth2.client.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
importorg.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
importorg.springframework.security.oauth2.client.resource.OAuth2ResourceServer;
importorg.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceServer;
importorg.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceServer;
importorg.springframework.security.oauth2.client.token.grant.code.flow.AuthorizationCodeFlowResourceServer;
importorg.springframework.security.oauth2.client.token.store.JwtAccessTokenConverter;
importorg.springframework.security.oauth2.client.token.store.JwtClientCredentials;
@Configuration
@EnableAuthorizationCodeResourceOwnerClientRegistries
@EnableResourceServer
publicclassSecurityConfigextendsResourceServerConfigurerAdapter{
privatefinalAuthenticationManagerauthenticationManager;
publicSecurityConfig(AuthenticationManagerauthenticationManager){
this.authenticationManager=authenticationManager;
}
@Override
publicvoidconfigure(ResourceServerRequestMatcherRegistryregistry){
registry.resourceServer("/api/**")
.jwt()
.jwtAuthenticationConverter(jwtAccessTokenConverter());
}
@Override
publicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{
clients.inMemory()
.withClient("client_id")
.secret("client_secret")
.authorizedGrantTypes("authorization_code","client_credentials")
.scopes("read","write")
.redirectUris("http://localhost:8080/callback");
}
@Override
publicvoidconfigure(AuthorizationCodeResourceOwnerClientRegistryregistry){
registry.register("resource_owner")
.authorizationCodeFlow(flow())
.scopes("read","write")
.redirectUris("http://localhost:8080/callback");
}
privateAuthorizationCodeFlowResourceServerflow(){
returnnewAuthorizationCodeFlowResourceServer(authenticationManager,resourceServer());
}
privateOAuth2ResourceServerresourceServer(){
returnnewClientCredentialsResourceServer(newJwtClientCredentials("client_id","client_secret"),jwtAccessTokenConverter());
}
privateJwtAccessTokenConverterjwtAccessTokenConverter(){
JwtAccessTokenConverterconverter=newJwtAccessTokenConverter();
converter.setSecret("secret");
returnconverter;
}
}
在上面的配置中,我们定义了一个OAuth2客户端,支持授权码和客户端凭证两种授权方式。同时,我们还配置了一个资源服务器,用于处理JWT令牌。
###1.7SpringSecurity6.x的异步认证与授权
SpringSecurity6.x支持异步认证和授权,这可以显著提高应用程序的性能,尤其是在高并发场景下。异步处理可以通过配置`AuthenticationManager`和`AuthorizationManager`来实现。
```java
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.authentication.AuthenticationManager;
importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
importorg.springframework.security.core.Authentication;
importorg.springframework.security.core.AuthenticationException;
importorg.springframework.security.core.context.SecurityContextHolder;
importorg.springframework.security.core.userdetails.UserDetailsService;
importorg.springframework.security.core.userdetails.UsernameNotFoundException;
importorg.springframework.security.crypto.password.PasswordEncoder;
importorg.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
importorg.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
importorg.springframework.security.oauth2.client.userinfo.OAuth2UserService;
importorg.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
importorg.springframework.security.oauth2.core.user.OAuth2UserRequest;
importorg.springframework.security.oauth2.core.user.OAuth2User;
importorg.springframework.security.oauth2.core.user.DefaultOAuth2User;
importorg.springframework.security.oauth2.core.user.OAuth2UserAttributes;
importorg.springframework.security.oauth2.core.OAuth2AuthenticationException;
importorg.springframework.scheduling.annotation.Async;
importorg.springframework.scheduling.annotation.EnableAsync;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
@Configuration
@EnableAsync
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
privatefinalUserDetailsServiceuserDetailsService;
privatefinalPasswordEncoderpasswordEncoder;
privatefinalClientRegistrationRepositoryclientRegistrationRepository;
@Autowired
publicSecurityConfig(UserDetailsServiceuserDetailsService,PasswordEncoderpasswordEncoder,ClientRegistrationRepositoryclientRegistrationRepository){
this.userDetailsService=userDetailsService;
this.passwordEncoder=passwordEncoder;
this.clientRegistrationRepository=clientRegistrationRepository;
}
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
@Bean
publicAuthenticationManagerauthenticationManagerBean()throwsException{
returnsuper.authenticationManagerBean();
}
@Bean
publicOAuth2UserService<OAuth2UserRequest,OAuth2User>oAuth2UserService(){
returnnewDefaultOAuth2UserService(){
@Override
@Async
publicOAuth2UserloadUser(OAuth2UserRequestuserRequest)throwsOAuth2AuthenticationException{
OAuth2UserAttributesattributes=super.loadUser(userRequest).getAttributes();
Stringusername=attributes.getName();
try{
returnuserDetailsService.loadUserByUsername(username);
}catch(UsernameNotFoundExceptione){
thrownewOAuth2AuthenticationException("Usernotfound",e);
}
}
};
}
}
在上面的配置中,我们使用了`@Async`注解来异步加载用户信息。`OAuth2UserService`的`loadUser`方法被标记为异步,这意味着用户信息的加载不会阻塞主线程,从而提高了认证性能。
###1.8SpringSecurity6.x的安全事件与日志
SpringSecurity6.x提供了丰富的安全事件和日志功能,帮助开发者监控和记录安全相关的操作。SpringSecurity的事件系统基于`ApplicationEvent`,而日志功能则依赖于SLF4J和Logback。
```java
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.context.ApplicationListener;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.core.Authentication;
importorg.springframework.security.core.AuthenticationEvent;
importorg.springframework.security.core.AuthenticationException;
importorg.springframework.security.core.session.SessionCreatedEvent;
importorg.springframework.security.core.session.SessionDestroyedEvent;
importorg.springframework.security.web.authentication.AuthenticationSuccessHandler;
importorg.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
@Configuration
publicclassSecurityEventConfig{
privatestaticfinalLoggerlogger=LoggerFactory.getLogger(SecurityEventConfig.class);
@Bean
publicAuthenticationSuccessHandlerauthenticationSuccessHandler(){
SimpleUrlAuthenticationSuccessHandlersuccessHandler=newSimpleUrlAuthenticationSuccessHandler();
successHandler.setSuccessUrl("/home");
returnsuccessHandler;
}
@Configuration
publicstaticclassAuthenticationSuccessEventListenerimplementsApplicationListener<AuthenticationSuccessEvent>{
@Override
publicvoidonApplicationEvent(AuthenticationSuccessEventevent){
Authenticationauthentication=event.getAuthentication();
("Authenticationsuccessforuser:{}",authentication.getName());
}
}
@Configuration
publicstaticclassSessionCreatedEventListenerimplementsApplicationListener<SessionCreatedEvent>{
@Override
publicvoidonApplicationEvent(SessionCreatedEventevent){
("Sessioncreatedforuser:{}",event.getPrincipal());
}
}
@Configuration
publicstaticclassSessionDestroyedEventListenerimplementsApplicationListener<SessionDestroyedEvent>{
@Override
publicvoidonApplicationEvent(SessionDestroyedEventevent){
("Sessiondestroyedforuser:{}",event.getPrincipal());
}
}
}
在上面的配置中,我们定义了三个事件监听器:
-`AuthenticationSuccessEventListener`:监听认证成功事件,记录成功认证的用户。
-`SessionCreatedEventListener`:监听会话创建事件,记录创建会话的用户。
-`SessionDestroyedEventListener`:监听会话销毁事件,记录销毁会话的用户。
###1.9SpringSecurity6.x的跨站请求伪造(CSRF)防护
跨站请求伪造(CSRF)是一种常见的网络攻击方式,SpringSecurity6.x提供了内置的CSRF防护机制。默认情况下,SpringSecurity会禁用CSRF保护,但在某些场景下(如单页应用程序)需要启用CSRF保护。
```java
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.csrf()
.enable()
.and()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上面的配置中,我们通过`.csrf().enable()`启用了CSRF保护。SpringSecurity会自动生成CSRF令牌,并在表单中嵌入该令牌,以防止CSRF攻击。
###1.10SpringSecurity6.x的会话管理
会话管理是SpringSecurity的重要组成部分,它负责管理用户的会话状态。SpringSecurity6.x提供了多种会话管理策略,如HTTP会话、数据库会话和分布式会话。
```java
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.sessionManagement()
.sessionFixation()
.none()
.and()
.sessionCreationPolicy(HttpSecuritySessionCreationPolicy.NEVER)
.and()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上面的配置中,我们通过`.sessionManagement()`配置了会话管理策略:
-`.sessionFixation().none()`:禁用会话固定攻击。
-`.sessionCreationPolicy(HttpSecuritySessionCreationPolicy.NEVER)`:禁止创建新的会话。
##一、SpringSecurity6.x核心概念与架构概述(续)
###1.11SpringSecurity6.x的记住我功能
记住我(RememberMe)功能允许用户在一定时间内自动登录,从而提高用户体验。SpringSecurity6.x提供了内置的记住我功能,支持多种记住我实现方式,如Cookie-based和数据库-based。
```java
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.rememberMe()
.key("rememberMeKey")
.rememberMeParameter("rememberMe")
.and()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上面的配置中,我们通过`.rememberMe()`配置了记住我功能:
-`.key("rememberMeKey")`:设置记住我Cookie的密钥。
-`.rememberMeParameter("rememberMe")`:设置表单中的记住我参数。
###1.12SpringSecurity6.x的HTTP头安全
HTTP头安全是提高应用程序安全性的重要手段,SpringSecurity6.x提供了多种HTTP头安全配置,如X-Frame-Options、X-Content-Type-Options、Strict-Transport-Security等。
```java
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.headers()
.frameOptions().sameOrigin()
.and()
.contentSecurityPolicy("default-src'self';script-src'self''unsafe-inline';")
.and()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上面的配置中,我们通过`.headers()`配置了HTTP头安全:
-`.frameOptions().sameOrigin()`:设置X-Frame-Options为`SAMEORIGIN`,防止点击劫持。
-`.contentSecurityPolicy("default-src'self';script-src'self''unsafe-inline';")`:设置内容安全策略,限制脚本来源。
###1.13SpringSecurity6.x的数据库集成
SpringSecurity6.x支持与多种数据库集成,如MySQL、PostgreSQL、MongoDB等。通过集成数据库,我们可以存储用户信息、权限数据等,从而实现更灵活的安全管理。
```java
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
importorg.springframework.security.core.userdetails.User;
importorg.springframework.security.core.userdetails.UserDetailsService;
importorg.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
importorg.springframework.security.crypto.password.PasswordEncoder;
importvisioning.JdbcUserDetailsManager;
importjavax.sql.DataSource;
@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
privatefinalDataSourcedataSource;
privatefinalPasswordEncoderpasswordEncoder;
publicSecurityConfig(DataSourcedataSource,PasswordEncoderpasswordEncoder){
this.dataSource=dataSource;
this.passwordEncoder=passwordEncoder;
}
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder);
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
@Bean
@Override
publicUserDetailsServiceuserDetailsService(){
returnnewJdbcDaoImpl(){
@Override
protectedvoidadditionalConfig(){
setDataSource(dataSource);
}
};
}
@Bean
publicJdbcUserDetailsManageruserDetailsManager(){
JdbcUserDetailsManagermanager=newJdbcUserDetailsManager();
manager.setDataSource(dataSource);
manager.setPasswordEncoder(passwordEncoder);
returnmanager;
}
}
在上面的配置中,我们通过`JdbcDaoImpl`和`JdbcUserDetailsManager`将SpringSecurity与数据库集成:
-`JdbcDaoImpl`:用于从数据库加载用户信息。
-`JdbcUserDetailsManager`:用于管理用户详细信息。
###1.14SpringSecurity6.x的单元测试
单元测试是确保SpringSecurity配置正确性的重要手段。SpringSecurity提供了丰富的测试支持,包括`MockMvc`、`SecurityMockMvc`等。
```java
importorg.junit.jupiter.api.Test;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.security.test.context.support.WithMockUser;
importorg.springframework.test.web.servlet.MockMvc;
importstaticorg.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
importstaticorg.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
importstaticorg.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
publicclassSecurityConfigTest{
@Autowired
privateMockMvcmockMvc;
@Test
publicvoidtestPublic()throwsException{
mockMvc.perform(get("/public/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello,public!"));
}
@Test
@WithMockUser(username="admin",roles="ADMIN")
publicvoidtestAdmin()throwsException{
mockMvc.perform(get("/admin/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello,admin!"));
}
@Test
@WithMockUser(username="user",roles="USER")
publicvoidtestReadFail()throwsException{
mockMvc.perform(get("/admin/hello"))
.andExpect(status().isUnauthorized());
}
}
在上面的测试中,我们使用了`@WithMockUser`注解来模拟不同的用户角色,并测试不同的请求路径。通过这些测试,我们可以验证SpringSecurity的权限控制配置是否正确。
##一、SpringSecurity6.x核心概念与架构概述(续)
###1.15SpringSecurity6.x的模块化设计
SpringSecurity6.x采用了模块化设计,这意味着开发者可以根据需求选择不同的模块进行集成。SpringSecurity的核心模块包括认证、授权、会话管理、CSRF保护等,而扩展模块则包括OAuth2、JWT、SAML等。
这种模块化设计使得SpringSecurity非常灵活,开发者可以根据应用程序的需求选择合适的模块进行集成。例如,如果应用程序需要支持OAuth2认证,开发者只需要引入SpringSecurityOAuth2模块即可。
###1.16SpringSecurity6.x的性能优化
SpringSecurity6.x在性能方面进行了多项优化,包括缓存、异步处理、数据库集成等。以下是一些常见的性能优化策略:
####1.16.1缓存
缓存是提高应用程序性能的重要手段,SpringSecurity6.x支持多种缓存策略,如EHCache、Redis等。通过缓存用户信息、权限数据等,可以显著提高认证和授权的性能。
```java
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
importorg.springframework.security.core.userdetails.UserCache;
importorg.springframework.security.core.userdetails.cache.ConcurrentMapUserCache;
importorg.springframework.security.core.use
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 全球资管行业市场前景及投资研究报告:组合个性化税务效率化
- 废化纤加工处理工操作知识能力考核试卷含答案
- 沥青装置操作工岗前道德考核试卷含答案
- 球拍球网制作工岗前保密考核试卷含答案
- 苯酚丙酮装置操作工班组评比能力考核试卷含答案
- 固态电解质制造工岗前成果转化考核试卷含答案
- 棘皮类养殖工岗前变更管理考核试卷含答案
- 井下作业工具工岗前技能实操考核试卷含答案
- 铸轧熔炼工岗前师带徒考核试卷含答案
- 酚醛树脂装置操作工班组评比考核试卷含答案
- 生物资产管理办法
- 安庆市2026届中考一模数学试题含解析
- 2024年吉林省高职高专单独招生考试数学试卷真题(精校打印)
- 小儿癫痫发作护理查房
- 中学食堂饭卡管理制度
- 春妆 春天清新妆容技巧与春风共舞
- 道路高程测量成果记录表-自动计算
- JG/T 160-2004混凝土用膨胀型、扩孔型建筑锚栓
- 2025年度财务决算和2025年度财务预算报告
- 购房者临时居住协议
- 中考物理试题卷及答案
评论
0/150
提交评论