Spring Security 认证
Spring Security 是一个基于过滤器链来提供认证和授权功能的框架,本文主要分析其中的认证过程
过滤器链
过滤器链如下图所示,过滤器链中主要是第二部分用于进行认证。本文分析 UsernamePasswordAuthenticationFilter,它用于处理表单提交的登录请求。SecurityContextPersistenceFilter 主要用于从请求读取或向响应装入认证信息 securityContext
认证处理流程
认证用户名和密码
UsernamePasswordAuthenticationFilter 的 attemptAuthentication 方法处理认证
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
username = (username != null) ? username : "";
username = username.trim();
String password = obtainPassword(request);
password = (password != null) ? password : "";
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// 向token中添加一些详细信息
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
- 当用户在登录页面输入用户名和密码后,进入 org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter 类的 attemptAuthentication 方法。这个方法会读取请求中的用户名和密码,并生成 UsernamePasswordAuthenticationToken 这个用于认证的 token
- 调用 setDetails 方法,向 token 中添加一些详细信息,具体就是请求的 ip、session 的信息
- 调用 ProviderManager 中的 authenticate 进行认证工作
ProviderManager 的 authenticate 方法进行认证工作
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
int currentPosition = 0;
int size = this.providers.size();
// 遍历所有的providers
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
// 如果provider不支持认证此请求,跳过
continue;
}
try {
// 此provider进行认证
result = provider.authenticate(authentication