spring security 支持多个认证方法

问尤龙の时光 该配合你演出的我,却视而不见。。 本文由博客端 http://www.wenyoulong.com 主动推送

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;

到此就可以实现多认证器。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2989 引用 • 8141 回帖 • 596 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    895 引用 • 1443 回帖 • 559 关注
  • 开发
    32 引用 • 156 回帖 • 1 关注

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...