Spring Boot Security自定义AuthenticationProvider

以下是一个简单的示例,展示如何使用AuthenticationProvider自定义身份验证。首先,创建一个继承自标准AuthenticationProvider的类,并实现authenticate方法。

import com.kamier.security.web.service.MyUser;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
 
import java.util.HashMap;
import java.util.Map;
 
public class MobilecodeAuthenticationProvider implements AuthenticationProvider {
 
    private UserDetailsService userDetailsService;
 
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
 
        MobilecodeAuthenticationToken mobilecodeAuthenticationToken = (MobilecodeAuthenticationToken) authentication;
        String phone = mobilecodeAuthenticationToken.getPhone();
        String mobileCode = mobilecodeAuthenticationToken.getMobileCode();
        System.out.println("登陆手机号:" + phone);
        System.out.println("手机验证码:" + mobileCode);
 
        // 模拟从redis中读取手机号对应的验证码及其用户名
        Map dataFromRedis = new HashMap();
        dataFromRedis.put("code", "6789");
        dataFromRedis.put("username", "admin");
 
        // 判断验证码是否一致
        if (!mobileCode.equals(dataFromRedis.get("code"))) {
            throw new BadCredentialsException("验证码错误");
        }
 
        // 如果验证码一致,从数据库中读取该手机号对应的用户信息
        MyUser loadedUser = (MyUser) userDetailsService.loadUserByUsername(dataFromRedis.get("username"));
        if (loadedUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        } else {
            MobilecodeAuthenticationToken result = new MobilecodeAuthenticationToken(loadedUser, null, loadedUser.getAuthorities());
            return result;
        }
    }
 
    @Override
    public boolean supports(Class> aClass) {
        return MobilecodeAuthenticationToken.class.isAssignableFrom(aClass);
    }
 
    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
}

 注意这里的supports方法,是实现多种认证方式的关键,认证管理器AuthenticationManager会通过这个supports方法来判定当前需要使用哪一种认证方式

上面的就是只支持MobilecodeAuthenticationToken

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
 
/**
 * 手机验证码认证信息,在UsernamePasswordAuthenticationToken的基础上添加属性 手机号、验证码
 */
public class MobilecodeAuthenticationToken extends AbstractAuthenticationToken {
    private static final long serialVersionUID = 530L;
    private Object principal;
    private Object credentials;
    private String phone;
    private String mobileCode;
 
 
    public MobilecodeAuthenticationToken(String phone, String mobileCode) {
        super(null);
        this.phone = phone;
        this.mobileCode = mobileCode;
        this.setAuthenticated(false);
    }
 
    public MobilecodeAuthenticationToken(Object principal, Object credentials, Collection extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }
 
    public Object getCredentials() {
        return this.credentials;
    }
 
    public Object getPrincipal() {
        return this.principal;
    }
 
    public String getPhone() {
        return phone;
    }
 
    public String getMobileCode() {
        return mobileCode;
    }
 
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        if (isAuthenticated) {
            throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        } else {
            super.setAuthenticated(false);
        }
    }
 
    public void eraseCredentials() {
        super.eraseCredentials();
        this.credentials = null;
    }
}
用户名密码

针对用户名密码方式,我们可以直接使用自带的DaoAuthenticationProvider以及对应的UsernamePasswordAuthenticationToken。

实现UserDetailService

UserDetailService服务用以返回当前登录用户的用户信息,可以每一种认证方式实现对应的UserDetailService,也可以使用同一个。这里我们使用同一个UserDetailService服务。(在provider中指定调用哪一个UserDetailService)

最后

在配置器中我们去实例化一个认证管理器AuthenticationManager,这个认证管理器中包含了两个认证器,分别是MobilecodeAuthenticationProvider(手机验证码)、DaoAuthenticationProvider(用户名密码)。

下面的只是名字不同改成自己的provider名字即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值