spring security 通过定义多个 AuthenticationProvider 来实现不同的认证方式。
1、自定义认证器
自定义认证器可以通过实现 AuthenticationProvider 接口来实现,这个接口,一共有两个方法
public interface AuthenticationProvider {
/**
* Performs authentication with the same contract as
* {@link org.springframework.security.authentication.AuthenticationManager#authenticate(Authentication)}
* .
* @param authentication the authentication request object.
* @return a fully authenticated object including credentials. May return
* <code>null</code> if the <code>AuthenticationProvider</code> is unable to support
* authentication of the passed <code>Authentication</code> object. In such a case,
* the next <code>AuthenticationProvider</code> that supports the presented
* <code>Authentication</code> class will be tried.
* @throws AuthenticationException if authentication fails.
*/
Authentication authenticate(Authentication authentication) throws AuthenticationException;
/**
* Returns <code>true</code> if this <Code>AuthenticationProvider</code> supports the
* indicated <Code>Authentication</code> object.
* <p>
* Returning <code>true</code> does not guarantee an
* <code>AuthenticationProvider</code> will be able to authenticate the presented
* instance of the <code>Authentication</code> class. It simply indicates it can
* support closer evaluation of it. An <code>AuthenticationProvider</code> can still
* return <code>null</code> from the {@link #authenticate(Authentication)} method to
* indicate another <code>AuthenticationProvider</code> should be tried.
* </p>
* <p>
* Selection of an <code>AuthenticationProvider</code> capable of performing
* authentication is conducted at runtime the <code>ProviderManager</code>.
* </p>
* @param authentication
* @return <code>true</code> if the implementation can more closely evaluate the
* <code>Authentication</code> class presented
*/
boolean supports(Class<?> authentication);
}
第一个方法参数是 Authencation,通过 Authencation 我们又可以自定义 token,也是通过实现 Authencation 来自定义 token,这个 token 会在第二个方法中使用;
第二个方法用于判断当前的认证其是否支持指定类型的 token;
2、自定义实现一个认证器
/**
* @author Mr.Wen
* @version 1.0
* @date 2021-08-19 14:20
*/
@Service
public class SecurityAuthenticationProvider implements AuthenticationProvider {
@Resource
private UserDetailsServiceImpl userDetailsService;
@Resource
private SecurityPasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
if(StringUtils.isBlank(username)){
throw new UsernameNotFoundException("username用户名不可以为空");
}
if(StringUtils.isBlank(password)){
throw new BadCredentialsException("密码不可以为空");
}
//获取用户信息
SecurityUserDetails user = (SecurityUserDetails)userDetailsService.loadUserByUsername(username);
//比较前端传入的密码明文和数据库中加密的密码是否相等
if (!passwordEncoder.matches(password, user.getPassword())) {
//发布密码不正确事件
throw new BadCredentialsException("password密码不正确");
}
//获取用户权限信息
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
return new SecurityAuthenticationToken(user, password, authorities);
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(SecurityAuthenticationToken.class);
}
}
UserDetails 和对应的 service 是自己实现的,密码处理器也是自己实现的,这些都无需关心,换成自己系统的实现就可以了,第一个方法,就是认证,返回一个 token 交给 spring security 后续流程处理;第二个方法判断当前 token 是不是认证其支持的 token。
3、配置多认证器
再 spring security 的配置类中,配置认证器。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 加入自定义的安全认证
auth.
authenticationProvider(securityAuthenticationProvider)
.authenticationProvider(getKmairCasAuthenticationProvider());
}
第一个 provider 是用 spring 注入的,第二个则是再方法中创建了 provider;
到此就可以实现多认证器。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于