Spring Security 之多AuthenticationProvider认证模式实现

AuthenticationProvider实现ProviderManager会按照加入认证请求链中的顺序来验证,前文的源码分析及实现原理已经说的很清楚了,本文直接看代码实现;

AuthenticationProvider认证类UserSmsAuthenticationProvider实现

/**
 * @Description: 用户自定义身份认证, 短信验证码模式
 * @Package: cn.appblog.security.oauth2.provider.UserSmsAuthenticationProvider
 * @Version: 1.0
 */
@Slf4j
@Component
public class UserSmsAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserAuthDetailsService authUserDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ApplicationEventPublisher publisher;

    /**
     * 认证处理,返回一个Authentication的实现类则代表认证成功,返回null则代表认证失败
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //测试,正式环境应该根据登录认证的通道来进行认证
        String username = authentication.getName();
        String smsCode = (String) authentication.getCredentials();
        log.info("smsCode: {}", smsCode);
        if (StringUtils.isBlank(username)) {
            throw new UsernameNotFoundException("username用户名不可以为空");
        }
        if (StringUtils.isBlank(smsCode)) {
            throw new BadCredentialsException("验证码不可以为空");
        }
        //获取用户信息
        UserDetails user = authUserDetailsService.loadUserByUsername(username);
        String smsCodeCache = "888888";
        //比较前端传入的短信验证码明文和预置的短信验证码是否相等
        if (!smsCodeCache.equals(smsCode)) {
            //发布短信验证码不正确事件
            publisher.publishEvent(new UserLoginFailedEvent(authentication));
            throw new BadCredentialsException("sms_code验证码不正确");
        }
        //获取用户权限信息
        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        return new UsernamePasswordAuthenticationToken(user, smsCode, authorities);
    }

    /**
     * 如果该AuthenticationProvider支持传入的Authentication对象,则返回true
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(UsernamePasswordAuthenticationToken.class);
    }
}

AuthenticationProvider认证类UserAuthenticationProvider实现

/**
 * @Description: 用户自定义身份认证
 * @Package: cn.appblog.security.oauth2.provider.UserAuthenticationProvider
 * @Version: 1.0
 */
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserAuthDetailsService authUserDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ApplicationEventPublisher publisher;

    /**
     * 认证处理,返回一个Authentication的实现类则代表认证成功,返回null则代表认证失败
     */
    @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("密码不可以为空");
        }
        //获取用户信息
        UserDetails user = authUserDetailsService.loadUserByUsername(username);
        //比较前端传入的密码明文和数据库中加密的密码是否相等
        if (!passwordEncoder.matches(password, user.getPassword())) {
            //发布密码不正确事件
            publisher.publishEvent(new UserLoginFailedEvent(authentication));
            throw new BadCredentialsException("password密码不正确");
        }
        //获取用户权限信息
        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        return new UsernamePasswordAuthenticationToken(user, password, authorities);
    }

    /**
     * 如果该AuthenticationProvider支持传入的Authentication对象,则返回true
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(UsernamePasswordAuthenticationToken.class);
    }
}

WebSecurityConfigurerAdapter安全配置类实现

/**
 * Spring Security认证服务中的相关实现重新定义
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // 加入自定义的安全认证
    auth.userDetailsService(this.authUserDetailsService)
            .passwordEncoder(this.passwordEncoder())
            .and()
            .authenticationProvider(smsAuthenticationProvider())
            .authenticationProvider(authenticationProvider());
}

测试验证

用户密码:123456
短信验证码:888888

(1)访问:http://localhost:9003/oauth/token?username=user&password=123456&grant_type=password&client_id=client_password&client_secret=secret

{
    "access_token":"ec55d1fcfc00407daa48f9784818dd69",
    "token_type":"bearer",
    "refresh_token":"3d6d773ac8f74766b243255f71e1011a",
    "expires_in":59,
    "scope":"all",
    "client_id":"client_password"
}

(2)访问:http://localhost:9003/oauth/token?username=user&password=888888&grant_type=password&client_id=client_password&client_secret=secret

{
    "access_token":"dd4ce15181da44169607caa842c3c4a7",
    "token_type":"bearer",
    "refresh_token":"07325d5d761940a69fbbd9fccf449ddf",
    "expires_in":59,
    "scope":"all",
    "client_id":"client_password"
}

本文转载参考 原文 并加以调试

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/20/implementation-of-multiple-authenticationprovider-authentication-patterns-in-spring-security/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Spring Security 之多AuthenticationProvider认证模式实现
多AuthenticationProvider实现ProviderManager会按照加入认证请求链中的顺序来验证,前文的源码分析及实现原理已经说的很清楚了,本文直接看代码实现; Authen……
<<上一篇
下一篇>>
文章目录
关闭
目 录