1. PasswordEncoder(密码加密器)
PasswordEncoder 用于对用户密码进行加密和验证。在 Spring Security 中,推荐使用BCryptPasswordEncoder。
// 定义一个密码编码器接口,用于对密码进行加密和匹配验证
public interface PasswordEncoder {
// 对原始密码(CharSequence 类型)进行编码(加密),返回加密后的字符串
String encode(CharSequence var1);
// 判断用户输入的原始密码(var1)与存储的加密密码(var2)是否匹配
boolean matches(CharSequence var1, String var2);
// 默认方法,用于判断当前存储的加密密码是否需要升级(比如更换了更安全的加密算法)
// 默认返回 false,表示不需要升级
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}
常见的加密方法介绍:
BCryptPasswordEncoder
算法:BCrypt 是一个基于加盐的密码哈希算法,它设计上能够防止暴力破解攻击。
特点:
-
加盐:每次加密都会生成一个不同的盐值,防止相同密码的密文相同。
-
计算成本:支持调整加密的计算复杂度(通过"工作因子"参数),更高的工作因子意味着更强的安全性。
-
用途:适合用来保护用户密码,防止常见的破解攻击(如字典攻击和暴力攻击)。
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
NoOpPasswordEncoder
算法:该加密器直接返回明文密码,而不进行任何加密。不推荐用于生产环境,仅适用于测试或其他无需加密的场景。
特点:
-
不进行任何密码加密操作。
-
不安全,任何人都可以看到密码的明文。
-
用途:仅用于演示或测试。
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
Pbkdf2PasswordEncoder
算法:PBKDF2(Password-Based Key Derivation Function 2)是一种基于密码的密钥推导函数,广泛用于加密存储密码。
特点:
-
加盐:每次加密都会生成不同的盐值。
-
支持迭代次数:PBKDF2 允许你配置迭代次数,迭代次数越多,密码验证所需的计算量越大,安全性越高。
-
适用性:相较于 BCrypt,它在计算上更灵活,支持更多配置项。
@Bean
public PasswordEncoder passwordEncoder() {
return new Pbkdf2PasswordEncoder();
}
SCryptPasswordEncoder
算法:Scrypt 是一种记忆硬度密码哈希函数,它相较于其他算法需要更多的内存,旨在抵抗大规模并行化攻击(例如通过 GPU 进行的暴力破解)。
特点:
-
相较于 PBKDF2 和 BCrypt,Scrypt 需要更多的内存来计算密文,从而有效地抵抗硬件加速的破解。
-
可以调节内存和迭代次数,增加破解难度。
-
用途:适用于对高安全性有要求的场景,尤其是在抵抗 GPU 破解攻击方面更具优势。
@Bean
public PasswordEncoder passwordEncoder() {
return new SCryptPasswordEncoder();
}
Argon2PasswordEncoder
算法:Argon2 是最新的一种密码哈希算法,获得了密码学界的广泛认可,特别是它在内存和时间复杂度方面的控制,使其特别适用于密码保护。
特点:
-
采用 盐值 和 工作因子。
-
可以通过内存和时间成本来调节加密难度。
-
相比于其他密码哈希算法,Argon2 更具安全性。
-
用途:适合需要高安全性的场景,尤其是在抵抗暴力破解和并行计算方面。
@Bean
public PasswordEncoder passwordEncoder() {
return new Argon2PasswordEncoder();
}
总结:
-
BCrypt 是目前最常用的密码加密方式,适合大多数应用。
-
NoOpPasswordEncoder 仅适用于测试,生产环境中不推荐使用。
-
Pbkdf2PasswordEncoder 提供更多配置选项,适合需要灵活控制加密过程的场景。
-
SCryptPasswordEncoder 和 Argon2PasswordEncoder 提供更强的防御机制,尤其适用于高安全性要求的场景。
public class PasswordEncoderTest {
private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); @Test public void testPasswordEncoder() { String password = "123456"; String encodedPassword = passwordEncoder.encode(password); System.out.println("加密后密文:"+encodedPassword); // 验证密码是否匹配 boolean matches = passwordEncoder.matches(password, encodedPassword); System.out.println("密码匹配结果:"+matches); }
}
2、UserDetailsService(用户信息服务)
UserDetailsService 是一个接口,用于从数据库加载用户信息(用户名、密码、角色等)。我们需要实现它,并在自定义逻辑中查询用户。
UserDetailsService 的作用:
-
用户认证:提供用户认证所需的用户信息
-
数据源抽象:将用户数据的获取方式与认证逻辑解耦
-
灵活性:可以自定义从任何数据源(数据库、LDAP、内存等)加载用户
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
通常我们需要实现自己的 UserDetailsService,从数据库中查询用户信息。
UserDetails 是 Spring Security 中表示用户信息的接口,通常我们会创建一个类实现此接口或使用框架提供的实现类(如 org.springframework.security.core.userdetails.User)。
3. DaoAuthenticationProvider(认证提供者)
DaoAuthenticationProvider 是 Spring Security 的默认认证提供者。它依赖于 UserDetailsService 和 PasswordEncoder。DaoAuthenticationProvider 是 Spring Security 中最核心的认证提供者(AuthenticationProvider)实现之一,专门用于基于用户名/密码的表单认证。
/**
* 配置密码编码器 Bean,使用 BCrypt 强散列加密算法对用户密码进行加密存储和验证
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 配置 DaoAuthenticationProvider Bean,用于基于数据库的用户认证
* 设置用户信息服务(userDetailsService)和密码编码器(passwordEncoder)
* @return
*/
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService); // 设置自定义用户详情服务
authProvider.setPasswordEncoder(passwordEncoder()); // 设置密码编码器,用于密码加密与验证
return authProvider;
}
4. SecurityFilterChain(过滤器链配置)
Spring Security 的过滤器链通过 SecurityFilterChain 进行配置。以下是常见配置项的解析:
1、CSRF(跨站请求伪造防护)
在开发阶段,可以禁用 CSRF 防护:
.csrf(csrf -> csrf.disable())
在生产环境,建议开启 CSRF 防护,并为特定接口添加白名单(Spring Security 5.x 中,在6.0中部分方法发生变化):
.csrf(csrf -> csrf.ignoringAntMatchers("/api/**"))
// 默认启用CSRF保护
csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
// 禁用CSRF(前后端分离常见做法)
csrf().disable();
2、授权规则
通过 authorizeHttpRequests 配置路由访问规则:
http.authorizeHttpRequests(auth -> auth.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
permitAll()、hasRole()、authenticated()对比:
|---------------------|------------|------------|--------------|
| 方法 | 是否需要登录 | 是否检查角色 | 典型使用场景 |
| permitAll() | ❌ 不需要 | ❌ 不检查 | 首页、登录页、公开API |
| authenticated() | ✔️ 需要 | ❌ 不检查 | 普通用户后台、个人中心 |
| hasRole("XXX") | ✔️ 需要 | ✔️ 检查指定角色 | 管理员后台、权限敏感操作 |
3、自定义登录页面
通过 formLogin 配置自定义登录行为:
.formLogin(form -> form
.loginPage("/login") // 登录页面路径
.loginProcessingUrl("/perform_login") // 登录表单提交路径
.defaultSuccessUrl("/home", true) // 登录成功后跳转页面
.failureUrl("/login?error") // 登录失败后跳转页面
.permitAll()
)
// 如果是前后端分离的项目,完全禁用表单登录功能
.formLogin().disable()
4、注销配置
通过 logout 配置用户退出登录后的行为:
.logout(logout -> logout
.logoutUrl("/logout") // 退出登录 URL
.logoutSuccessUrl("/login?logout") // 退出成功后跳转页面
.permitAll()
)
.logout().disable() // 禁用默认的/logout端点
5、HTTP Basic 认证配置
HTTP Basic 认证是 HTTP 协议定义的一种简单的认证机制,它通过 Authorization 请求头传递凭证,使用 Base64 编码(非加密)用户名和密码,是 RFC 7617 定义的标准认证方式
基本工作原理:
-
客户端访问受保护资源
-
服务器返回 401 Unauthorized 和 WWW-Authenticate: Basic 头
-
浏览器弹出登录对话框
-
用户输入凭据后,浏览器发送 Authorization: Basic base64(username:password) 头
-
服务器验证凭据并返回资源或再次 401
.httpBasic(); // 启用HTTP Basic认证
.httpBasic().disable(); // 禁用HTTP Basic
6、会话管理
会话管理是Web安全的重要组成部分,它控制着用户登录后的会话行为。Spring Security提供了强大的会话管理功能,包括会话并发控制、会话过期处理等。
限制每个用户只能有一个会话,并配置会话过期后的行为:
.sessionManagement(session -> session
.maximumSessions(1) // 每个用户限制一个会话
.expiredUrl("/login?expired") // 会话过期后跳转页面
)
//声明不依赖 Session 维护认证状态。
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态
7、Remember-Me 功能
Remember-Me 是 Spring Security 提供的一种持久化登录机制,允许用户在关闭浏览器后再次访问网站时无需重新登录,通常通过 Cookie 实现。
.rememberMe()
.key("uniqueAndSecretKey") // 加密密钥
.tokenValiditySeconds(86400 * 30) // 30天有效期
.rememberMeParameter("remember-me") // 表单参数名
.rememberMeCookieName("remember-me") // Cookie名
.tokenRepository(persistentTokenRepository()); // 持久化存储
// 禁用传统的基于Cookie的Remember-Me
.rememberMe(remember -> remember.disable());
8、headers安全头配置
Spring Security 的 headers() 配置用于添加各种安全相关的 HTTP 响应头,这些头部可以帮助浏览器防范常见攻击。
.headers(headers -> headers
// 禁用Spring Security提供的所有默认安全头
.defaultsDisabled()
// 启用缓存控制头,防止敏感信息被缓存
.cacheControl(withDefaults())
// 启用内容类型选项头,防止MIME嗅探攻击
.contentTypeOptions(withDefaults())
// 启用HTTP严格传输安全头(HSTS),强制使用HTTPS
.httpStrictTransportSecurity(withDefaults())
// 启用X-Frame-Options头,防止点击劫持攻击
.frameOptions(withDefaults())
// 启用X-XSS-Protection头,启用浏览器内置的XSS防护
.xssProtection(withDefaults())
// 启用Referrer-Policy头,控制Referer信息的发送策略
.referrerPolicy(withDefaults())
)
9、SpringSecurity 异常处理配置
Spring Security 的 exceptionHandling() 用于自定义认证和授权过程中的异常处理行为。
http
.exceptionHandling() // 开启异常处理配置
.authenticationEntryPoint(authenticationEntryPoint()) // 认证入口点
.accessDeniedHandler(accessDeniedHandler()) // 访问拒绝处理器
10、跨域资源共享(CORS)配置
Spring Security 默认禁用 CORS,需要显式配置才能启用跨域支持。
.cors().configurationSource(corsConfigurationSource())
.cors().disable() // 同源不需要CORS

cors与csrf使用策略
1. 传统Web应用(同源)
http
.cors().disable() // 同源不需要CORS
.csrf().csrfTokenRepository(new CookieCsrfTokenRepository()) // 启用CSRF
2. 前后端分离项目(跨域)
http
.cors().configurationSource(corsConfigurationSource()).and() // 配置CORS
.csrf().disable() // 通常禁用CSRF,改用JWT等Token方案
/**
* 定义一个Bean,用于配置跨域资源共享(CORS)策略
* @return
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
// 创建CORS配置对象
CorsConfiguration config = new CorsConfiguration();
// 设置允许的来源,只允许来自 https://trusted.com 的请求
config.setAllowedOrigins(Arrays.asList("https://trusted.com"));
// 设置允许的HTTP方法,仅允许 GET 和 POST 请求
config.setAllowedMethods(Arrays.asList("GET", "POST"));
// 允许发送凭据(如Cookies、Authorization头等)
config.setAllowCredentials(true);
// 创建基于URL的CORS配置源,用于将CORS配置应用到具体的URL路径上
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 将上述CORS配置应用到所有路径(/** 表示所有接口)
source.registerCorsConfiguration("/**", config);
// 返回CORS配置源,供Spring Security或Web框架使用
return source;
}
配置 HTTP 安全过滤器链
/**
* 配置 HTTP 安全过滤器链
* * 该过滤器链的优先级为1,表示它将优先于其他过滤器链执行
* @param http
* @return
* @throws Exception
*/
@Bean
@Order(1)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
// 1. 授权配置:设置所有请求(anyRequest)都需要用户认证(authenticated)
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
// 2. 表单登录:启用Spring Security默认的表单登录功能(包括登录页和登录处理逻辑)
.formLogin(withDefaults())
// 3. HTTP Basic认证:启用HTTP Basic方式的认证(浏览器弹窗方式)
.httpBasic(withDefaults())
// 4. 记住我功能:启用"记住我"功能,默认有效期通常为14天
.rememberMe(withDefaults())
// 5. 登出功能:启用默认的登出逻辑,如清除会话、cookie等
.logout(withDefaults())
// 6. CSRF保护:启用跨站请求伪造(CSRF)防护,默认是开启的
.csrf(withDefaults())
// 7. 会话管理:配置会话相关策略
.sessionManagement(session -> session
// 如果需要则创建会话(默认策略),即不主动创建,按需使用
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
// 同一用户最多只能有一个活跃会话
.maximumSessions(1)
// 当达到最大会话数时,不允许新登录(false表示允许新登录踢掉旧会话)
.maxSessionsPreventsLogin(false)
)
// 8. 安全头配置:自定义HTTP安全响应头
.headers(headers -> headers
// 禁用Spring Security提供的所有默认安全头
.defaultsDisabled()
// 启用缓存控制头,防止敏感信息被缓存
.cacheControl(withDefaults())
// 启用内容类型选项头,防止MIME嗅探攻击
.contentTypeOptions(withDefaults())
// 启用HTTP严格传输安全头(HSTS),强制使用HTTPS
.httpStrictTransportSecurity(withDefaults())
// 启用X-Frame-Options头,防止点击劫持攻击
.frameOptions(withDefaults())
// 启用X-XSS-Protection头,启用浏览器内置的XSS防护
.xssProtection(withDefaults())
// 启用Referrer-Policy头,控制Referer信息的发送策略
.referrerPolicy(withDefaults())
)
// 9. 异常处理:使用Spring Security默认的异常处理逻辑,如403、401等
.exceptionHandling(withDefaults())
// 10. CORS配置:配置跨域资源共享(CORS),默认是禁用的
.cors(withDefaults());
// 构建并返回配置好的安全过滤器链
return http.build();
}