一,先看流程图
二,步骤解析
1,springsecurity默认用户密码登陆
首先看用户名密码登陆的过滤器UsernamePasswordAuthenticationFilter
其继承了父类AbstractAuthenticationProcessingFilter
看其doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Authentication authResult;
try {
authResult = attemptAuthentication(request, response);//获取用户信息
。。。
}
catch (AuthenticationException failed) {
unsuccessfulAuthentication(request, response, failed);//失败处理器
return;
}
。。。
successfulAuthentication(request, response, chain, authResult);//设置用户信息到上下文context
}
2,看方法attemptAuthentication(request, response); 是抽象
调用子类的 attemptAuthentication 方法。子类有很多实现,以用户密码登陆方式UsernamePasswordAuthenticationFilter为例,
查看其attemptAuthentication 方法
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
。。。
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);//如果是社交登陆则是SocialAuthenticationToken
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);//获取用户信息
}
}
3,查看方法 this.getAuthenticationManager().authenticate(authRequest);
跟到ProviderManager的authenticate方法
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();//获取token类型
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
boolean debug = logger.isDebugEnabled();
Iterator var8 = this.getProviders().iterator();
while(var8.hasNext()) {
AuthenticationProvider provider = (AuthenticationProvider)var8.next();
if (provider.supports(toTest)) {//不同的认证方式,找到支持的
result = provider.authenticate(authentication);//主流程
。。。
}
}
4,查看方法 provider.authenticate(authentication);
跟到AbstractUserDetailsAuthenticationProvider的authenticate方法
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
。。。
try {
user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);//获取用户信息
} catch (UsernameNotFoundException var6) {
。。。
try {
this.preAuthenticationChecks.check(user);//检查是否冻结,过期等
this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);检查密码
} catch (AuthenticationException var7) {
。。。
return this.createSuccessAuthentication(principalToReturn, authentication, user);//创建返回新的用户认证信息,包括权限
}
5,查看this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);/
跟到DaoAuthenticationProvider的retrieveUser方法。里面的loadUserByUsername方法就是自己自定义的获取用户信息方法
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
try {
UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);//获取用户信息,
} catch (UsernameNotFoundException var4) {
。。。
}
6,
获取到用户信息后回到
第1步的successfulAuthentication(request, response, chain, authResult);
把用户信息设置到上下文中
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
。。。
SecurityContextHolder.getContext().setAuthentication(authResult);//设置上下文
。。。
rememberMeServices.loginSuccess(request, response, authResult);
。。。
successHandler.onAuthenticationSuccess(request, response, authResult);//登陆成功处理器
}