Spring Security 认证与授权机制源码解析
结合之前的
IOC
、AOP
、事务管理
, 这一篇讲讲Spring 的安全性,以下是小弟对Spring Security
的一些理解,以及在真实面试中碰到的一些问题做了些整理,欢迎各位大佬一起观摩指点!!
一、Spring Security 简介
Spring Security 是 Spring 生态中专门用于安全控制的框架,主要用于 身份认证(Authentication) 和 授权(Authorization)。它能够无缝集成到 Spring Boot,并提供了一套默认的安全策略,如表单登录、OAuth2 支持、密码加密、跨站请求伪造(CSRF)防护等。
Spring Security 的核心功能可以归纳为以下几点:
- 认证(Authentication): 识别用户身份,如账号密码登录、Token 登录等。
- 授权(Authorization): 确定用户是否有访问某些资源的权限,如基于角色(Role)或权限(Permission)控制访问。
- 安全性防护(Security Protection): 防止 CSRF 攻击、XSS 攻击等常见安全漏洞。
二、Spring Security 认证流程(源码解析)
2.1 认证的核心组件
Spring Security 认证流程涉及多个核心组件,主要包括:
SecurityFilterChain
: 通过一组 过滤器(Filter) 进行身份认证和授权检查。AuthenticationManager
: 认证管理器,负责验证用户身份。AuthenticationProvider
: 认证提供者,支持不同的认证方式(如密码、OAuth2、JWT)。UserDetailsService
: 用于加载用户信息的服务,可以从数据库或其他存储介质获取用户信息。PasswordEncoder
: 密码加密器,确保密码存储安全。
2.2 认证流程解析
Spring Security 认证过程由 过滤器链 完成,主要流程如下:
- 用户发起请求 (通常是登录请求,如
/login
)。 UsernamePasswordAuthenticationFilter
拦截请求,提取用户名和密码。- 交给
AuthenticationManager
认证 ,由AuthenticationProvider
进行验证。 - 通过
UserDetailsService
加载用户信息,校验用户名和密码。 - 如果认证通过,生成
Authentication
对象并存入 SecurityContext,否则返回 401 未授权错误。
源码解析
java
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
String username = obtainUsername(request);
String password = obtainPassword(request);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
return this.getAuthenticationManager().authenticate(authRequest);
}
2.3 自定义用户认证
java
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getPassword(), getAuthorities(user));
}
private Collection<? extends GrantedAuthority> getAuthorities(User user) {
return user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}
三、Spring Security 授权机制解析
3.1 授权核心组件
Spring Security 的授权机制依赖于以下核心组件:
AccessDecisionManager
: 负责决策当前用户是否可以访问某个资源。SecurityContextHolder
: 维护当前用户的安全上下文信息。GrantedAuthority
: 表示用户的权限(如ROLE_ADMIN
、ROLE_USER
)。@PreAuthorize
/@Secured
注解: 进行方法级别的权限控制。
3.2 基于角色的权限控制
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
).formLogin(withDefaults());
return http.build();
}
}
3.3 方法级别的权限控制
java
@Service
public class OrderService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteOrder(Long orderId) {
// 仅管理员可删除订单
}
}
四、高频面试题
Q1:Spring Security 的认证流程是怎样的?
A1:Spring Security 的认证流程包括:UsernamePasswordAuthenticationFilter
拦截请求 → 交给 AuthenticationManager
认证 → AuthenticationProvider
验证用户名密码 → UserDetailsService
加载用户信息 → 认证成功存入 SecurityContext
。
Q2:Spring Security 如何进行授权?
A2:授权方式包括:
- 基于 URL 访问控制 (
antMatchers
) - 基于 方法注解 (
@PreAuthorize
/@Secured
) - 自定义
AccessDecisionManager
进行更复杂的权限判断。
Q3:如何自定义用户认证?
A3:可以实现 UserDetailsService
接口,并在 loadUserByUsername
方法中从数据库查询用户信息,再返回 UserDetails
实例。
Q4:Spring Security 如何与 JWT 结合?
A4:可以通过 OncePerRequestFilter
解析 JWT 并手动创建 UsernamePasswordAuthenticationToken
,然后存入 SecurityContextHolder
,实现无状态认证。
五、总结
- Spring Security 通过 过滤器链 实现身份认证和授权。
- 认证流程涉及
AuthenticationManager
、AuthenticationProvider
和UserDetailsService
。 - 授权可以通过 URL 访问控制、方法注解、表达式等方式实现。
- 在实际项目中,通常需要 自定义认证逻辑,如从数据库加载用户信息,或结合 JWT 进行无状态认证。