spring boot整合spring security(二)--手机号验证码登陆

概述

spring security默认使用的是用户名密码的登陆,如果想要增加一种登陆方式,

就要仿照源码中用户名密码登陆的方式, 手写一套手机号验证码登陆校验, 话不多说, 开干!

搭建基础架构

搭建项目基础架构工作, 在(一)中已经完成, 这里直接在其基础上继续开发

认证流程

  • 1.进入 UsernamePasswordAuthenticationFilter 然后构建一个没有认证的 UsernamePasswordAuthenticationToken
  • 2.随后交给 AuthenticationManager 进行验证,
  • 3.AuthenticationManager 找到对应的 AuthenticationProvider进行认证
  • 4.AuthenticationProvider找到上下文中的UserDetailsService 中寻找用户然后对比
  • 5.验证成功返回 Authentication 放入 SecurityContextHolder中

这里需要自定义一个token,filter和provider

定义token

参考UsernamePasswordAuthenticationToken, 其中principal是用户名, credentials是密码,
由于这里只有手机号, 不需要密码, 所以, 将其中有关credentials的去除, 复制下来即可
在这里插入图片描述

自定义SmsCodeAuthenticationToken如下

package com.etouch.security.security.smslogin;

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import java.util.Collection;

/*
 *这一步的作用是为了替换原有系统的 UsernamePasswordAuthenticationToken 用来做验证
 *
 * 代码都是从UsernamePasswordAuthenticationToken 里粘贴出来的
 *
 */
public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken {
   
    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

    /**
     * 在 UsernamePasswordAuthenticationToken 中该字段代表登录的用户名,
     * 在这里就代表登录的手机号码
     */
    private final Object principal;

    /**
     * 构建一个没有鉴权的 SmsCodeAuthenticationToken
     */
    public SmsCodeAuthenticationToken(Object principal) {
   
        super(null);
        this.principal = principal;
        setAuthenticated(false);
    }

    /**
     * 构建拥有鉴权的 SmsCodeAuthenticationToken
     */
    public SmsCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
   
        super(authorities);
        this.principal = principal;
        super.setAuthenticated(true); // must use super, as we override
    }



    // ~ Methods
    // 剩下的方法不用动就行了 就是从 UsernamePasswordAuthenticationToken 里粘贴出来的
    // ========================================================================================================

    public Object getCredentials() {
   
        return null;
    }

    public Object getPrincipal() {
   
        return this.principal;
    }

    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");
        }

        super.setAuthenticated(false);
    }

    @Override
    public void eraseCredentials() {
   
        super.eraseCredentials();
    }
}

定义过滤器filter

同样参照UsernamePasswordAuthenticationFilter,将和password有关的去除, 略微修改以下, 即可完成

同样参照UsernamePasswordAuthenticationFilter图片位

自定义的SmsCodeAuthenticationFilter代码如下

package com.etouch.security.security.smslogin;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 短信登录的鉴权过滤器,模仿 UsernamePasswordAuthenticationFilter 实现
*/
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
   
    /**
     * form表单中手机号码的字段name
     */
    public static final String SPRING_SECURITY_FORM_MOBILE_KEY = "phone";

    private String mobileParameter = SPRING_SECURITY_FORM_MOBILE_KEY;
    /**
     * 是否仅 POST 方式
     */
    private boolean postOnly = true;

    public SmsCodeAuthenticationFilter() {
   
        // 短信登录的请求 post 方式的 /sms/login
        super(new AntPathRequestMatcher("/sys/login/phone", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
   
        if (postOnly && !request.getMethod().equals("POST")) {
   
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        // 电话号码
        String mobile = obtainUsername(request);
        if (StringUtils.isEmpty(mobile)) {
   
            throw new AuthenticationServiceException("电话号码不能为空");
        }
        return this.getAuthenticationManager().authenticate(new SmsCodeAuthenticationToken(mobile));
    }


    protected String obtainUsername(HttpServletRequest request) {
   
        return request.getParameter(mobileParameter);
    }

    protected String obtainPassword(HttpServletRequest request) {
   
        return request.getParameter(mobileParameter);
    }
}

接下来是自定义手机号验证码登陆鉴证器provider

代码如下

package com.etouch.security.security.smslogin;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

意田天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值