Java学习手册:Spring Security 安全框架
一、Spring Security 简介
Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架,用于保护 Java 应用程序,尤其是基于 Spring 的应用。它构建在 Spring 框架之上,能够轻松地集成到基于 Spring 的应用程序中,包括 Spring Boot 应用。
Spring Security 提供了以下核心功能:
- 认证(Authentication) :确认用户身份的过程。支持多种认证方式,如基于表单的认证、HTTP 基本认证、基于 Token 的认证(如 JWT - JSON Web Tokens)等。
- 授权(Authorization) :确定已认证用户是否有权访问特定资源。通过定义访问规则来实现,例如基于角色(如管理员、普通用户)或权限(如读取权限、写入权限)的访问控制。
- 防止常见攻击 :提供了内置的 CSRF(跨站请求伪造)保护、XSS(跨站脚本攻击)保护、SQL 注入防护、点击劫持防护等功能。
二、Spring Security 的基本架构
Spring Security 通过一系列的过滤器(Filter)来实现其安全功能。这些过滤器构成了 Spring Security 的核心架构,主要的过滤器包括:
- CsrfFilter :用于防止跨站点请求伪造攻击。
- BasicAuthenticationFilter :支持 HTTP 的标准 Basic Auth 的身份验证模块。
- UsernamePasswordAuthenticationFilter :支持 Form 表单形式的身份验证模块。
- DefaultLoginPageGeneratingFilter 和 DefaultLogoutPageGeneratingFilter :用于自动生成登录页面和注销页面。
- AuthorizationFilter :负责授权模块。
这些过滤器通过 FilterChainProxy
进行管理,FilterChainProxy
会根据匹配规则(如 URL 匹配)决定使用哪个 SecurityFilterChain
。而 SecurityFilterChain
又由零到多个 Filter 组成,这些 Filter 完成实际的安全功能。
三、Spring Security 的配置
1. 添加依赖
在 Spring Boot 项目中,只需添加 Spring Security 的启动器依赖,Spring Boot 会自动配置基本的 Spring Security 功能:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
添加依赖后,Spring Boot 会自动配置一个默认的用户(用户名是 “user”)和一个随机生成的密码,应用启动时会在控制台打印出来。
2. 基本配置
可以通过在 application.properties
或 application.yml
文件中进行一些基本配置,如设置默认的用户名、密码和角色:
spring.security.user.name=admin
spring.security.user.password=admin123
spring.security.user.roles=ADMIN
3. 自定义配置
通过创建一个配置类来实现更复杂的 Spring Security 配置:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests((authz) -> authz.requestMatchers("/user/login").anonymous().requestMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated()).formLogin(Customizer.withDefaults()).httpBasic(Customizer.withDefaults());return http.build();}
}
在上述配置中:
authorizeHttpRequests
用于定义请求的授权规则。这里配置了/user/login
路径允许匿名访问,/admin/**
路径只有具有ADMIN
角色的用户才能访问,其他所有请求都需要经过身份验证。formLogin
启用了基于表单的登录功能。httpBasic
启用了 HTTP 基本认证功能。
四、用户认证与授权
1. 自定义用户认证
可以通过创建一个自定义的 UserDetailsService
类来实现用户认证:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 根据用户名从数据库或其他存储中获取用户信息if ("admin".equals(username)) {return User.builder().username("admin").password("{noop}admin123").roles("ADMIN").build();} else {throw new UsernameNotFoundException("User not found");}}
}
然后在配置类中注入自定义的 UserDetailsService
,并配置认证管理器:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated().and().formLogin().and().logout().logoutUrl("/logout").invalidateHttpSession(true).deleteCookies("JSESSIONID");}
}
2. 角色权限访问
在控制器中定义一个 Admin 资源类,只有 admin 用户才能进行访问:
@RequestMapping("admin")
@RestController
public class AdminController {@GetMapping("resourse")public String AdminRole(){return "这是只有管理员用户才能访问的资源";}
}
五、密码加密
Spring Security 提供了多种密码编码器,如 BCryptPasswordEncoder
,用于对用户密码进行加密存储。
在配置类中使用 BCryptPasswordEncoder
:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests((authz) -> authz.requestMatchers("/user/login").anonymous().requestMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated()).httpBasic(Customizer.withDefaults());return http.build();}
}
可以创建一个测试类,将所有用户的密码改为 BCrypt 加密后的数据:
@Test
public void testUpdateAllPasswords() {BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String encodedPassword = encoder.encode("123456");LambdaUpdateWrapper<Users> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.set(Users::getPassword, encodedPassword);boolean result = usersMapper.update(null, updateWrapper) > 0;if (result) {System.out.println("所有用户的密码更新成功!");} else {System.out.println("密码更新失败!");}
}
六、高级安全配置
1. 跨域资源共享(CORS)
当应用需要从不同的域访问资源时,需要配置 CORS:
http.cors().configurationSource(corsConfigurationSource()).and().authorizeRequests()// 其他配置
;private CorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.addAllowedOrigin("*");configuration.addAllowedMethod("*");configuration.addAllowedHeader("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;
}
这个配置允许来自任何源的请求,任何 HTTP 方法和任何请求头,在开发环境中比较方便,但在生产环境中可能需要更严格的限制。
2. Remember - Me 功能
Spring Security 的 Remember - Me 功能允许用户在关闭浏览器并重新打开后,仍然保持登录状态。通过在用户登录成功后,在客户端(浏览器)存储一个加密的 Cookie 来实现。在后续的请求中,Spring Security 会检查这个 Cookie 来自动认证用户。可以在 Spring Security 配置中添加如下内容:
http.rememberMe().tokenValiditySeconds(86400).key("myRememberMeKey");
这里设置了 Remember - Me 令牌的有效期为 86400 秒(一天),并指定了一个密钥用于加密和解密 Cookie。
七、总结
Spring Security 是 Spring 生态系统中的重要组成部分,提供了全面的安全功能,包括身份验证、授权、防止常见攻击等。通过集成到 Spring Boot 应用中,可以快速实现安全配置,保护应用程序的数据和资源安全。掌握 Spring Security 的基本配置、用户认证与授权、密码加密以及高级安全配置等内容,是构建安全可靠的 Spring 应用的关键。