spring security多个认证管理器,spring security使用
目录
authenticationprovidersecurityconfiguradatteruserdailsservicetokenfilter登录过程在了解过安全性的认证器后,如果想自定义登陆,只要实现认证提供者还有对应的证明就可以了
Authentication
首先要创建一个自定义的身份验证,安全性提供了一个证明的子类抽象认证令牌
我们实现这个类可以了,他已经实现了证明的一些方法
公共类NamePassAuthenticationToken扩展了AbstractAuthenticationToken { private static final long serial version uid=520 l;私有最终对象主体;私有对象凭据;//提供第一次进来的构造方法公共名称PassAuthenticationToken(对象主体,对象凭据){超级((集合)null);this . principal=principal this . credentials=credentials this。set authenticated(false);}//提供填充证明的构造方法公共名称sauthenticationtoken(对象主体、对象凭据、集合?扩展授予权限authorities){ super(权限);this . principal=principal this . credentials=credentials super。set authenticated(真);} @覆盖公共对象get credentials(){返回此。全权证书;} @ Override public Object get principal(){ return this。本金;} @ Override public void set已验证(布尔值已验证)抛出IllegalArgumentException { if(已通过身份验证){ throw new IllegalArgumentException(无法将此标记设置为可信使用构造函数,该构造函数改为采用授予权限列表);} else { super。set authenticated(false);} } @ Override public void eraseCredentials(){ super。eraseCredentials();this.credentials=null}}这个类关键就是一个是认证的,一个没认证的的构造器
AuthenticationProvider
接着是认证提供者,需要实现他的鉴定方法
@ setter公共类名为sauthenticationprovider实现AuthenticationProvider { private CustomUserDetailsService userDetailsService;私有密码编码密码编码;@Override //具体认证逻辑公共验证验证(验证验证){
NamePassAuthenticationToken authenticationToken = (NamePassAuthenticationToken) authentication; String username = (String) authenticationToken.getPrincipal(); String password = (String) authenticationToken.getCredentials(); //让具体认证类去认证 UserDetails user = userDetailsService.loadUserByUsername(username); boolean matches = passwordEncoder.matches(password, user.getPassword()); if (!matches) { ResMsg.throwException(AuthExceptionGroup.AUTH_ERROR); } //填充Authentication NamePassAuthenticationToken authenticationResult = new NamePassAuthenticationToken(user, password, user.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } @Override //指定具体的Authentication //根据你指定的Authentication来找到具体的Provider public boolean supports(Class<?> authentication) { return NamePassAuthenticationToken.class.isAssignableFrom(authentication); }}
SecurityConfigurerAdapter
接着就是填充配置了
@Componentpublic class NamePassAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { @Autowired private CustomUserDetailsService customUserDetailsService; @Autowired private PasswordEncoder passwordEncoder; @Override public void configure(HttpSecurity http) { //phonePass provider NamePassAuthenticationProvider provider = new NamePassAuthenticationProvider(); provider.setUserDetailsService(customUserDetailsService); provider.setPasswordEncoder(passwordEncoder); http.authenticationProvider(provider); }}
接下来就是导入配置了
通常都会有一个实现了WebSecurityConfigurerAdapter的配置类
把配置类注入进来
@Autowiredprivate NamePassAuthenticationSecurityConfig namePassAuthenticationSecurityConfig; protected void configure(HttpSecurity http) throws Exception { http.apply(namePassAuthenticationSecurityConfig);}
UserDetailsService
UserDetailsService是具体的认证实现类
这个类就非常熟悉了,只需要实现他的loadUserByUsername方法,就可以实现认证了
@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { AuthmsViewAccount account = accountService.getAccount(username); if(account == null) { ResMsg.throwException(AUTH_ERROR); } if (account.getStatus() != 1) { ResMsg.throwException(ACCOUNT_HAS_BANED); } String spliceStaffInfo = String.format("%d-%s",account.getAccountId(),account.getUsername());//只要Collection<? extends GrantedAuthority> authorities//这个参数不为空,就表明认证通过,所以空集合也可以通过 return new User(spliceStaffInfo,account.getPassword(), AuthorityUtils.NO_AUTHORITIES); }
把认证结果填充到上下文中
TokenFilter
如果结合了Token,那么需要从token中识别该用户
@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String bearerToken = resolveToken(request); if (bearerToken != null && !"".equals(bearerToken.trim()) && SecurityContextHolder.getContext().getAuthentication() == null) { //从redis中获取该用户 NamePassAuthenticationToken namePassAuthenticationToken = authRedisHelper.get(bearerToken); if(namePassAuthenticationToken != null) { //将信息保存到上下文中 SecurityContextHolder.getContext().setAuthentication(namePassAuthenticationToken); } } chain.doFilter(request, response);}private String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) { return bearerToken.substring(7); } return null; }
public NamePassAuthenticationToken get(String bearerToken){ String spliceStaffInfo = (String)redisRepository.get(formatKey(bearerToken)); if(spliceStaffInfo == null) { return null; } return new NamePassAuthenticationToken(new AuthStaff(spliceStaffInfo),null,AuthorityUtils.NO_AUTHORITIES);}
登录过程
在登录的时候,就需要用到这个自定义的认证器了
// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 NamePassAuthenticationTokenNamePassAuthenticationToken authenticationToken = new NamePassAuthenticationToken(user.getUsername(), user.getPassword());//通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象 //AuthenticationManager会通过你传入的authenticationToken来找到具体的ProviderAuthentication authentication = authenticationManager.authenticate(authenticationToken);//填充用户信息到secrity中的user里User principal = (User) authentication.getPrincipal();//获取认证后的信息NamePassAuthenticationToken namePassAuthenticationToken = new NamePassAuthenticationToken(new AuthStaff(principal.getUsername()), null, authentication.getAuthorities());// 生成tokenString bearerToken = IdUtil.fastSimpleUUID();// 加载到reidsauthRedisHelper.set(bearerToken, namePassAuthenticationToken);
这样就实现了自定义的认证器了
到此这篇关于Spring Security自定义认证器的文章就介绍到这了,更多相关Spring Security自定义认证器内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。