Spring Security在内部维护一个过滤器链,其中每个过滤器都有特定的责任;
比如:
-
ChannelProcessingFilter
,因为它可能需要重定向到不同的协议 -
SecurityContextPersistenceFilter
,因此可以在web请求开头的SecurityContextHolder
中设置SecurityContext
,并且SecurityContext
的任何更改都可以复制到HttpSession
当web请求结束时(准备好与下一个web请求一起使用)等等…
登录流程解析
UsernamePasswordAuthenticationFilter
登录认证流程解析认证的是通过一个对应的过滤器UsernamePasswordAuthenticationFilter
此类是一个过滤器继承 AbstractAuthenticationProcessingFilter
既然是过滤器首先看 doFilter 逻辑
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
try {
//核心代码获取 Authentication
Authentication authenticationResult = attemptAuthentication(request, response);
if (authenticationResult == null) {
// return immediately as subclass has indicated that it hasn't completed
return;
}
this.sessionStrategy.onAuthentication(authenticationResult, request, response);
// Authentication success
if (this.continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
//验证成功后处理
successfulAuthentication(request, response, chain, authenticationResult);
}
catch (InternalAuthenticationServiceException failed) {
this.logger.error("An internal error occurred while trying to authenticate the user.", failed);
unsuccessfulAuthentication(request, response, failed);
}
catch (AuthenticationException ex) {
// Authentication failed
//认证失败后处理
unsuccessfulAuthentication(request, response, ex);
}
}
attemptAuthentication 是一个抽象方法,由 UsernamePasswordAuthenticationFilter实现
@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());
}
//获取用户名 其实就是request.getParam 获取
String username = obtainUsername(request);
username = (username != null) ? username : "";
username = username.trim();
//获取密码 其实就是request.getParam 获取
String password = obtainPassword(request);
password = (password != null) ? password : "";
//用户名和密码组装成 UsernamePasswordAuthenticationToken
Username