Spring Security 6 集成常见操作指南
一、核心依赖与基础配置
1. 添加 Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 集成JWT时添加 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
<!-- 集成OAuth2时添加 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
2. 安全配置类(SecurityFilterChain)
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
)
.csrf(CsrfConfigurer::disable) // 开发环境可禁用CSRF
.exceptionHandling(ex -> ex
.accessDeniedPage("/403")
);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
二、认证与授权核心操作
1. 自定义用户服务(UserDetailsService)
@Service
public class CustomUserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) {
return userRepository.findByUsername(username)
.map(user -> User.builder()
.username(user.getUsername())
.password(user.getPassword())
.roles(user.getRoles())
.build()
)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
}
2. 基于角色的访问控制
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
);
3. 方法级安全(@PreAuthorize)
@Service
public class DataService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteData(Long id) {
// 仅ADMIN可执行
}
}
三、高级功能集成
1. JWT 集成
- 生成JWT令牌:
public String generateToken(UserDetails userDetails) { return Jwts.builder() .setSubject(userDetails.getUsername()) .claim("roles", userDetails.getAuthorities()) .setExpiration(new Date(System.currentTimeMillis() + 86400000)) .signWith(SignatureAlgorithm.HS256, "secretKey") .compact(); }
- JWT验证过滤器:
public class JwtFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { String jwt = token.substring(7); Claims claims = Jwts.parser().setSigningKey("secretKey").parseClaimsJws(jwt).getBody(); String username = claims.getSubject(); UserDetails user = userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken( user, null, user.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(auth); } chain.doFilter(request, response); } }
2. OAuth2 集成
- 配置application.yml:
spring: security: oauth2: client: registration: google: client-id: YOUR_CLIENT_ID client-secret: YOUR_CLIENT_SECRET scope: profile, email provider: google: authorization-uri: https://accounts.google.com/o/oauth2/auth token-uri: https://oauth2.googleapis.com/token
3. 动态权限控制
- 从数据库加载权限:
public class DynamicAuthorityLoader { @Autowired private PermissionRepository permissionRepo; public List<GrantedAuthority> loadAuthorities(Long userId) { return permissionRepo.findByUserId(userId).stream() .map(perm -> new SimpleGrantedAuthority("ROLE_" + perm.getCode())) .collect(Collectors.toList()); } }
四、会话与安全管理
1. 记住我(Remember-Me)
http.rememberMe(remember -> remember
.key("uniqueAndSecret")
.tokenValiditySeconds(1209600) // 14天
);
2. 会话管理
http.sessionManagement(session -> session
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
);
3. 安全头配置
http.headers(headers -> headers
.contentSecurityPolicy("default-src 'self'")
.xssProtection(XssProtectionConfigurer::block)
);
五、测试与调试
1. 安全测试
@Test
@WithMockUser(username = "admin", roles = "ADMIN")
void testAdminAccess() throws Exception {
mockMvc.perform(get("/admin"))
.andExpect(status().isOk());
}
2. 日志审计
@EventListener
public void onAuthenticationSuccess(AuthenticationSuccessEvent event) {
logger.info("User {} logged in from {}",
event.getAuthentication().getName(),
event.getAuthenticationDetails());
}
六、迁移指南(5.x → 6.x)
-
配置类调整:
- 移除
@EnableWebSecurity
(6.x默认启用)。 - 替换
WebSecurityConfigurerAdapter
为SecurityFilterChain
Bean。
- 移除
-
路径匹配语法:
- 将
antMatchers("/api/**")
替换为requestMatchers("/api/**")
。
- 将
-
过滤器链控制:
- 使用
SecurityFilterChain
Bean显式定义多条链,通过@Order
控制优先级。
- 使用
七、最佳实践
- 密码安全:始终使用
BCryptPasswordEncoder
,避免明文存储。 - 最小权限原则:优先使用
hasAuthority()
替代hasRole()
实现细粒度控制。 - 性能优化:对高频查询接口,结合缓存减少
UserDetailsService
调用。 - 安全头防护:启用CSP、XSS防护等,防御常见Web攻击。
通过以上步骤,您可快速集成Spring Security 6并实现企业级安全控制。核心原则是最小权限、加密存储、日志审计,结合Spring Security 6的Lambda DSL和组件化设计,可显著提升配置可读性与维护性。