SpringSecurity使用指南(一)自定义JWT认证流程

SpringSecurity是一个非常强大的安全验证框架,它通过一个过滤器链完成了对资源的访问控制。security框架本身提供了多种验证方式,如OA,Session等,但是有些情况下还是无法满足用户的需求,故此security框架也有非常大的扩展性,它允许用户自定义认证流程,下面我们就结合security实现一个jwt认证流程。

拦截登录请求

security框架中通过UsernamePasswordAuthenticationFilter来拦截登录请求,并将登录信息封装为待验证的token对象。由于我们需要自定义认证流程,所以要继承UsernamePasswordAuthenticationFilter的父类实现自己的拦截器来构造token。

public class JwtAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
   

    public JwtAuthenticationProcessingFilter() {
   
        //该过滤器会拦截哪些路径和类型的请求
        super(new AntPathRequestMatcher("/Jwtlogin", "POST"));
    }

    /**
     * 该方法是实现将用户登录信息从request提取,并封装成一个未认证的token传给AuthenticationManager处理
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @return
     * @throws AuthenticationException
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
   
        try {
   
            String username=httpServletRequest.getParameter("username");
            String password=httpServletRequest.getParameter("password");

            JwtToken jwtToken=new JwtToken(username,password);
            //将请求的会话id,IP地址保存在token中
            jwtToken.setDetails(new WebAuthenticationDetails(httpServletRequest));
            //调用认证管理器对token进行认证
            Authentication authentication=this.getAuthenticationManager().authenticate(jwtToken);
            return authentication;
        }catch (Exception e)
        {
   
            throw new BadCredentialsException("校验凭证失败,"+e.getMessage());
        }
    }
}
实现token

由于JwtAuthenticationProcessingFilter会调用AuthenticationManager进行认证,而AuthenticationManager内部存在多个认证方式,它通过token的类型来选择其中一种进行验证,因此我们需要实现一个自己的token。

public class JwtToken extends AbstractAuthenticationToken {
   

    private Object Principal;

    private Object Credential;

    /**
     * 构造等待认证的token
     * @param principal
     * @param credential
     */
    public JwtToken(Object principal, Object credential) {
   
        super(null);
        Principal = principal;
        Credential = credential;
        //设置token状态为未认证
        setAuthenticated(false);
    }

    /**
     * 构造已认证的token
     * @param authorities
     * @param principal
     * @param credential
     */
    public JwtToken(Collection<? extends GrantedAuthority> authorities, Object principal, Object credential) {
   
    	//保存权限
        super(authorities);
        Principal = principal;
        Credential = credential;
        //设置token状态为已认证
        setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
   
        return this.Credential;
    }

    @Override
    public Object getPrincipal() {
   
        return this.Principal;
    }
}
实现认证方式

Security的认证方式都实现AuthenticationProvider接口,所以我们只需要这个接口就可以自定义认证方式了,这个接口有authenticate和supports两个方法,authenticate接收一个待认证的token作为参数,认证成功则重新构造一个已认证的token并返回。supports方法用于判断是否该认证方式支持哪种token。

public class JwtAuthProvider implements AuthenticationProvider{
   

    @Resource(name = "UserDetailServiceImpl")
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtPasswordEncoder encoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
   
        JwtToken jwtToken= (JwtToken) authentication;
        UserDetails details=userDetailsService.loadUserByUsername(jwtToken.getName());
        AuthenticationCheck(details,jwtToken);
        SecurityCheck(details);
        JwtToken token=new JwtToken(details.getAuthorities(),details,jwtToken.getCredentials())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值