spring security认证(登录)原理(UsernamePasswordAuthenticationFilter) 作者:马育民 • 2020-08-03 22:06 • 阅读:10137 过滤器`UsernamePasswordAuthenticationFilter`用于处理登录 [![](https://www.malaoshi.top/upload/pic/1/login.png)](https://www.malaoshi.top/upload/pic/1/login.png) 类图:https://www.malaoshi.top/upload/pic/1/login.png ``` public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password"; //表单控件名 private String usernameParameter = "username"; private String passwordParameter = "password"; private boolean postOnly = true; //匹配url:/login,并且是post方法 public UsernamePasswordAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); } public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { //请求方法是post if (this.postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); } else { String username = this.obtainUsername(request); String password = this.obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); this.setDetails(request, authRequest); //进入authenticate()方法 return this.getAuthenticationManager().authenticate(authRequest); } } ``` 通过`this.getAuthenticationManager().authenticate(authRequest);`方法,来到下面接口: ``` public interface AuthenticationManager { Authentication authenticate(Authentication var1) throws AuthenticationException; } ``` 找到该接口的实现类`ProviderManager`的下面代码: ``` 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; boolean debug = logger.isDebugEnabled(); Iterator var8 = this.getProviders().iterator(); while(var8.hasNext()) { AuthenticationProvider provider = (AuthenticationProvider)var8.next(); if (provider.supports(toTest)) { if (debug) { logger.debug("Authentication attempt using " + provider.getClass().getName()); } try { //通过该方法找到AuthenticationProvider接口 result = provider.authenticate(authentication); if (result != null) { this.copyDetails(authentication, result); break; } } catch (InternalAuthenticationServiceException | AccountStatusException var13) { this.prepareException(var13, authentication); throw var13; } catch (AuthenticationException var14) { lastException = var14; } } } ``` 通过接口找到类`AbstractUserDetailsAuthenticationProvider`,关键代码如下: ``` public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, () -> { return this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported"); }); String username = authentication.getPrincipal() == null ? "NONE_PROVIDED" : authentication.getName(); boolean cacheWasUsed = true; UserDetails user = this.userCache.getUserFromCache(username); if (user == null) { cacheWasUsed = false; try { //找到该方法,通过该方法,找到类DaoAuthenticationProvider user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication); } catch (UsernameNotFoundException var6) { this.logger.debug("User '" + username + "' not found"); if (this.hideUserNotFoundExceptions) { throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } throw var6; } ``` 找到其子类`DaoAuthenticationProvider`的`retrieveUser`方法: ``` protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { this.prepareTimingAttackProtection(); try { //通过loadUserByUsername()找到UserDetailsService接口 UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username); if (loadedUser == null) { throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation"); } else { return loadedUser; } } catch (UsernameNotFoundException var4) { this.mitigateAgainstTimingAttack(authentication); throw var4; } catch (InternalAuthenticationServiceException var5) { throw var5; } catch (Exception var6) { throw new InternalAuthenticationServiceException(var6.getMessage(), var6); } } ``` 接口`UserDetails`的实现类,用于封装登录用户信息 接口`UserDetailsService`的实现类,实现登录功能 原文出处:http://malaoshi.top/show_1EF60YyrM4Eq.html