Spring Security配置与权限控制完全指南
Spring Security 常规用法详解:从基础配置到高级控制
Spring Security 是 Java 领域最流行的安全框架之一,本文将深入讲解其常规用法,包括基础配置、自定义认证、方法级权限控制和 JWT 集成等核心功能。
一、基础配置
1.1 最小化安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
}
配置解析:
authorizeRequests()
:开始权限配置antMatchers("/public/**").permitAll()
:允许匿名访问/public路径anyRequest().authenticated()
:其他所有请求需要认证formLogin().loginPage("/login")
:自定义登录页路径
实践建议:
- 生产环境应启用CSRF防护(默认已启用)
- 静态资源(CSS/JS)应配置在permitAll路径中
- 登录页和退出端点通常需要开放访问权限
二、自定义用户认证
2.1 基于数据库的用户认证
@Bean
public UserDetailsService userDetailsService() {
return username -> {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
AuthorityUtils.createAuthorityList("ROLE_USER")
);
};
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
组件说明:
UserDetailsService
:核心接口,负责加载用户数据PasswordEncoder
:密码编码器,推荐使用BCrypt
认证流程:
实践建议:
- 密码必须加密存储,禁止明文
- 用户状态(启用/禁用)应通过UserDetails的isEnabled等方法控制
- 复杂系统可考虑实现自定义AuthenticationProvider
三、方法级权限控制
3.1 注解式权限控制
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
@Service
public class AdminService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
// 管理员专属操作
}
@PreAuthorize("#username == authentication.name")
public void updateProfile(String username, Profile profile) {
// 只能修改自己的资料
}
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long docId) {
// 返回后检查权限
}
}
注解说明:
@PreAuthorize
:方法执行前检查权限@PostAuthorize
:方法执行后检查返回值权限@Secured
:简单的角色检查
SpEL表达式示例:
hasRole('ADMIN')
:检查管理员角色#variable
:访问方法参数authentication.name
:当前用户名
实践建议:
- 优先使用
@PreAuthorize
而非@Secured
(功能更强大) - 复杂权限逻辑可封装为自定义PermissionEvaluator
- 服务层方法应进行权限检查,而不仅依赖Web层防护
四、JWT集成
4.1 JWT认证配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
4.2 JWT过滤器示例
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
String token = resolveToken(request);
if (token != null && validateToken(token)) {
Authentication auth = getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
private String resolveToken(HttpServletRequest request) {
// 从Header或Cookie中提取Token
}
private boolean validateToken(String token) {
// 验证Token有效性
}
private Authentication getAuthentication(String token) {
// 根据Token创建Authentication对象
}
}
JWT流程:
实践建议:
- 令牌应设置合理的过期时间
- 考虑实现令牌刷新机制
- 敏感操作应使用短期有效的令牌
- 生产环境应启用HTTPS保护令牌传输
五、最佳实践总结
- 分层防护:Web层+方法层双重防护
- 最小权限:遵循最小权限原则分配角色
- 防御CSRF:表单操作启用CSRF防护
- 密码安全:使用强哈希算法(BCrypt/Argon2)
- 监控审计:记录重要安全事件
- 定期复审:定期检查权限分配合理性
通过合理运用这些常规配置模式,可以构建既安全又灵活的应用程序防护体系。Spring Security的强大之处在于它的可扩展性,开发者可以根据实际需求在这些基础模式上进行定制开发。
评论已关闭