通过【从授权开始看源码】我们可以看到这里主要就是干了几件事情 - 通过filter 确定登录要过滤的url - 通过filter 确定生成的`AbstractAuthenticationToken` 比如 `UsernamePasswordAuthenticationToken` - 通过生成的`AbstractAuthenticationToken` 确定`AuthenticationProvider` - 通过`AuthenticationProvider` 最后调用 `authenticate()`方法最后进行授权 根据上面我们对自己对代码进行了一些封装 我们先来看`LoginAuthenticationFilter` ```java public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationTokenParser authenticationTokenParser; @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { AbstractAuthenticationToken authRequest = authenticationTokenParser.parse(requestBody); return this.getAuthenticationManager().authenticate(authRequest); } public void setAuthenticationTokenParser(AuthenticationTokenParser authenticationTokenParser) { this.authenticationTokenParser = authenticationTokenParser; } } ``` 这里的登录继承了`UsernamePasswordAuthenticationFilter` 里面写了 ```java public UsernamePasswordAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); } ``` 这就是为什么登录的接口是`/login`的原因 我们再来看看生成`AbstractAuthenticationToken `的方法 `AbstractAuthenticationToken authRequest = authenticationTokenParser.parse(requestBody);` 这里决定了生成什么token,将会决定后面的`AuthenticationProvider` 我们先来看`AdminAuthenticationProvider` ``` @Override public boolean supports(Class<?> authentication) { return AdminAuthenticationToken.class.isAssignableFrom(authentication); } ``` 这里决定`AdminAuthenticationToken` 是通过`AdminAuthenticationProvider` 进行校验 再来看下完整的`AdminAuthenticationProvider` 你就知道验证码在哪里校验的了,是不是很简单 ```java public class AdminAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { private final YamiUserDetailsService yamiUserDetailsService; private final PasswordEncoder passwordEncoder; @Override protected UserDetails retrieveUser(String username, Authentication authentication) throws BaseYamiAuth2Exception { UserDetails user; try { user = yamiUserDetailsService.loadUserByUsername(username); } catch (UsernameNotFoundExceptionBase var6) { throw new UsernameNotFoundExceptionBase("账号或密码不正确"); } if (!user.isEnabled()) { throw new UsernameNotFoundExceptionBase("账号已被锁定,请联系管理员"); } return user; } @Override protected void additionalAuthenticationChecks(UserDetails sysUser, Authentication authentication) throws BaseYamiAuth2Exception { AdminAuthenticationToken adminAuthenticationToken = (AdminAuthenticationToken) authentication; String kaptchaKey = SecurityConstants.SPRING_SECURITY_RESTFUL_IMAGE_CODE + adminAuthenticationToken.getSessionUUID(); String kaptcha = RedisUtil.get(kaptchaKey); RedisUtil.del(kaptchaKey); if(StrUtil.isBlank(adminAuthenticationToken.getImageCode()) || !adminAuthenticationToken.getImageCode().equalsIgnoreCase(kaptcha)){ throw new ImageCodeNotMatchExceptionBase("验证码有误"); } String encodedPassword = sysUser.getPassword(); String rawPassword = authentication.getCredentials().toString(); // 密码不正确 if (!passwordEncoder.matches(rawPassword,encodedPassword)){ throw new BadCredentialsExceptionBase("账号或密码不正确"); } } @Override protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) { AdminAuthenticationToken result = new AdminAuthenticationToken(user, authentication.getCredentials()); result.setDetails(authentication.getDetails()); return result; } } ```