这里谈谈自定义认证 不使用自定义认证的 WebSecurityConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class); @Resource(name = "userDetailsService") private UserDetailsService userDetailsService; @Resource(name = "passwordEncoder") private PasswordEncoder passwordEncoder; @Override protected void configure (AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder) ; } }
不使用自定义认证的验证类 AbstractUserDetailsAuthenticationProvider
这里只看 authenticate
验证的方法,根据自己的理解,我写上了注释,////
为重点强调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 public Authentication authenticate (Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, () -> 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 { user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { logger.debug("User '" + username + "' not found" ); if (hideUserNotFoundExceptions) { throw new BadCredentialsException (messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials" ,"Bad credentials" )); } else { throw notFound; } } Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract" ); } try { preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { cacheWasUsed = false ; user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; } } postAuthenticationChecks.check(userDetail); if (!cacheWasUsed) { this .userCache.putUserInCache(user); } Object principalToReturn = user; if (forcePrincipalAsString) { principalToReturn = user.getUsername(); } return createSuccessAuthentication(principalToReturn, authentication, user); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @startuml Title "Authentication类图" interface Principal interface Authentication interface AuthenticationManager interface AuthenticationProvider abstract class AbstractUserDetailsAuthenticationProvider class ProviderManager class DaoAuthenticationProvider interface UserDetailsService Principal <|-- Authentication Authentication <.. AuthenticationManager AuthenticationManager <|-- ProviderManager ProviderManager o--> AuthenticationProvider AuthenticationProvider <|.. AbstractUserDetailsAuthenticationProvider AbstractUserDetailsAuthenticationProvider <|-- DaoAuthenticationProvider UserDetailsService <.. AbstractUserDetailsAuthenticationProvider interface AuthenticationManager{ # Authentication authenticate(Authentication authentication) throws AuthenticationException; } abstract class AbstractUserDetailsAuthenticationProvider{ + public Authentication authenticate(Authentication authentication) throws AuthenticationException; +public boolean supports(Class<?> authentication); } @enduml
使用自定义认证的 WebSecurityConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class); private PasswordEncoder passwordEncoder; @Resource(name = "authenticationProvider") private AuthenticationProvider authenticationProvider; @Override protected void configure (AuthenticationManagerBuilder auth) throws Exception { auth .authenticationProvider(authenticationProvider) ; } }
自定义认证类 AuthenticationProviderImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 @Service("authenticationProvider") public class AuthenticationProviderImpl implements AuthenticationProvider { @Resource(name = "userDetailsService") private UserDetailsService userDetailsService; @Resource(name = "passwordEncoder") private PasswordEncoder passwordEncoder; @Override public Authentication authenticate (Authentication authenticate) throws AuthenticationException { UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authenticate; String username = token.getName(); UserDetails userDetails = null ; if (username != null ) { userDetails = userDetailsService.loadUserByUsername(username); } if (userDetails == null ) { throw new UsernameNotFoundException ("用户名/密码无效" ); } else if (!userDetails.isEnabled()) { System.out.println("jinyong用户已被禁用" ); throw new DisabledException ("用户已被禁用" ); } else if (!userDetails.isAccountNonExpired()) { System.out.println("guoqi账号已过期" ); throw new AccountExpiredException ("账号已过期" ); } else if (!userDetails.isAccountNonLocked()) { System.out.println("suoding账号已被锁定" ); throw new LockedException ("账号已被锁定" ); } else if (!userDetails.isCredentialsNonExpired()) { System.out.println("pingzheng凭证已过期" ); throw new CredentialsExpiredException ("凭证已过期" ); } String password = userDetails.getPassword(); if (!password.equals(token.getCredentials())) { throw new BadCredentialsException ("Invalid username/password" ); } return new UsernamePasswordAuthenticationToken (userDetails, password, userDetails.getAuthorities()); } @Override public boolean supports (Class<?> authentication) { return UsernamePasswordAuthenticationToken.class.equals(authentication); } }
本文地址: SpringBoot+Security+JWT进阶:一、自定义认证
推荐
SpringBoot+Security+JWT基础 SpringBoot+Security+JWT进阶:一、自定义认证 SpringBoot+Security+JWT进阶:二、自定义认证实践
本文地址: https://github.com/maxzhao-it/blog/post/53124/