当前位置: 移动技术网 > IT编程>开发语言>Java > Spring Security Oauth2.0 实现短信验证码登录示例

Spring Security Oauth2.0 实现短信验证码登录示例

2019年07月19日  | 移动技术网IT编程  | 我要评论

齐冠男,陈淑兰三级,奇特网

本文介绍了spring security oauth2.0 实现短信验证码登录示例,分享给大家,具体如下:

定义手机号登录令牌

/**
 * @author lengleng
 * @date 2018/1/9
 * 手机号登录令牌
 */
public class mobileauthenticationtoken extends abstractauthenticationtoken {

  private static final long serialversionuid = springsecuritycoreversion.serial_version_uid;

  private final object principal;

  public mobileauthenticationtoken(string mobile) {
    super(null);
    this.principal = mobile;
    setauthenticated(false);
  }

  public mobileauthenticationtoken(object principal,
                   collection<? extends grantedauthority> authorities) {
    super(authorities);
    this.principal = principal;
    super.setauthenticated(true);
  }

  public object getprincipal() {
    return this.principal;
  }

  @override
  public object getcredentials() {
    return null;
  }

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

手机号登录校验逻辑

/**
 * @author lengleng
 * @date 2018/1/9
 * 手机号登录校验逻辑
 */
public class mobileauthenticationprovider implements authenticationprovider {
  private userservice userservice;

  @override
  public authentication authenticate(authentication authentication) throws authenticationexception {
    mobileauthenticationtoken mobileauthenticationtoken = (mobileauthenticationtoken) authentication;
    uservo uservo = userservice.finduserbymobile((string) mobileauthenticationtoken.getprincipal());

    userdetailsimpl userdetails = builduserdeatils(uservo);
    if (userdetails == null) {
      throw new internalauthenticationserviceexception("手机号不存在:" + mobileauthenticationtoken.getprincipal());
    }

    mobileauthenticationtoken authenticationtoken = new mobileauthenticationtoken(userdetails, userdetails.getauthorities());
    authenticationtoken.setdetails(mobileauthenticationtoken.getdetails());
    return authenticationtoken;
  }

  private userdetailsimpl builduserdeatils(uservo uservo) {
    return new userdetailsimpl(uservo);
  }

  @override
  public boolean supports(class<?> authentication) {
    return mobileauthenticationtoken.class.isassignablefrom(authentication);
  }

  public userservice getuserservice() {
    return userservice;
  }

  public void setuserservice(userservice userservice) {
    this.userservice = userservice;
  }
}

登录过程filter处理

/**
 * @author lengleng
 * @date 2018/1/9
 * 手机号登录验证filter
 */
public class mobileauthenticationfilter extends abstractauthenticationprocessingfilter {
  public static final string spring_security_form_mobile_key = "mobile";

  private string mobileparameter = spring_security_form_mobile_key;
  private boolean postonly = true;

  public mobileauthenticationfilter() {
    super(new antpathrequestmatcher(securityconstants.mobile_token_url, "post"));
  }

  public authentication attemptauthentication(httpservletrequest request,
                        httpservletresponse response) throws authenticationexception {
    if (postonly && !request.getmethod().equals(httpmethod.post.name())) {
      throw new authenticationserviceexception(
          "authentication method not supported: " + request.getmethod());
    }

    string mobile = obtainmobile(request);

    if (mobile == null) {
      mobile = "";
    }

    mobile = mobile.trim();

    mobileauthenticationtoken mobileauthenticationtoken = new mobileauthenticationtoken(mobile);

    setdetails(request, mobileauthenticationtoken);

    return this.getauthenticationmanager().authenticate(mobileauthenticationtoken);
  }

  protected string obtainmobile(httpservletrequest request) {
    return request.getparameter(mobileparameter);
  }

  protected void setdetails(httpservletrequest request,
               mobileauthenticationtoken authrequest) {
    authrequest.setdetails(authenticationdetailssource.builddetails(request));
  }

  public void setpostonly(boolean postonly) {
    this.postonly = postonly;
  }

  public string getmobileparameter() {
    return mobileparameter;
  }

  public void setmobileparameter(string mobileparameter) {
    this.mobileparameter = mobileparameter;
  }

  public boolean ispostonly() {
    return postonly;
  }
}

生产token 位置

/**
 * @author lengleng
 * @date 2018/1/8
 * 手机号登录成功,返回oauth token
 */
@component
public class mobileloginsuccesshandler implements org.springframework.security.web.authentication.authenticationsuccesshandler {
  private logger logger = loggerfactory.getlogger(getclass());
  @autowired
  private objectmapper objectmapper;
  @autowired
  private clientdetailsservice clientdetailsservice;
  @autowired
  private authorizationservertokenservices authorizationservertokenservices;

  @override
  public void onauthenticationsuccess(httpservletrequest request, httpservletresponse response, authentication authentication) {
    string header = request.getheader("authorization");

    if (header == null || !header.startswith("basic ")) {
      throw new unapprovedclientauthenticationexception("请求头中client信息为空");
    }

    try {
      string[] tokens = extractanddecodeheader(header);
      assert tokens.length == 2;
      string clientid = tokens[0];
      string clientsecret = tokens[1];

      jsonobject params = new jsonobject();
      params.put("clientid", clientid);
      params.put("clientsecret", clientsecret);
      params.put("authentication", authentication);

      clientdetails clientdetails = clientdetailsservice.loadclientbyclientid(clientid);
      tokenrequest tokenrequest = new tokenrequest(maputil.newhashmap(), clientid, clientdetails.getscope(), "mobile");
      oauth2request oauth2request = tokenrequest.createoauth2request(clientdetails);

      oauth2authentication oauth2authentication = new oauth2authentication(oauth2request, authentication);
      oauth2accesstoken oauth2accesstoken = authorizationservertokenservices.createaccesstoken(oauth2authentication);
      logger.info("获取token 成功:{}", oauth2accesstoken.getvalue());

      response.setcharacterencoding(commonconstant.utf8);
      response.setcontenttype(commonconstant.content_type);
      printwriter printwriter = response.getwriter();
      printwriter.append(objectmapper.writevalueasstring(oauth2accesstoken));
    } catch (ioexception e) {
      throw new badcredentialsexception(
          "failed to decode basic authentication token");
    }
  }

  /**
   * decodes the header into a username and password.
   *
   * @throws badcredentialsexception if the basic header is not present or is not valid
   *                 base64
   */
  private string[] extractanddecodeheader(string header)
      throws ioexception {

    byte[] base64token = header.substring(6).getbytes("utf-8");
    byte[] decoded;
    try {
      decoded = base64.decode(base64token);
    } catch (illegalargumentexception e) {
      throw new badcredentialsexception(
          "failed to decode basic authentication token");
    }

    string token = new string(decoded, commonconstant.utf8);

    int delim = token.indexof(":");

    if (delim == -1) {
      throw new badcredentialsexception("invalid basic authentication token");
    }
    return new string[]{token.substring(0, delim), token.substring(delim + 1)};
  }
}

配置以上自定义

//**
 * @author lengleng
 * @date 2018/1/9
 * 手机号登录配置入口
 */
@component
public class mobilesecurityconfigurer extends securityconfigureradapter<defaultsecurityfilterchain, httpsecurity> {
  @autowired
  private mobileloginsuccesshandler mobileloginsuccesshandler;
  @autowired
  private userservice userservice;

  @override
  public void configure(httpsecurity http) throws exception {
    mobileauthenticationfilter mobileauthenticationfilter = new mobileauthenticationfilter();
    mobileauthenticationfilter.setauthenticationmanager(http.getsharedobject(authenticationmanager.class));
    mobileauthenticationfilter.setauthenticationsuccesshandler(mobileloginsuccesshandler);

    mobileauthenticationprovider mobileauthenticationprovider = new mobileauthenticationprovider();
    mobileauthenticationprovider.setuserservice(userservice);
    http.authenticationprovider(mobileauthenticationprovider)
        .addfilterafter(mobileauthenticationfilter, usernamepasswordauthenticationfilter.class);
  }
}

在spring security 配置 上边定一个的那个聚合配置

/**
 * @author lengleng
 * @date 2018年01月09日14:01:25
 * 认证服务器开放接口配置
 */
@configuration
@enableresourceserver
public class resourceserverconfiguration extends resourceserverconfigureradapter {
  @autowired
  private filterurlspropertiesconifg filterurlspropertiesconifg;
  @autowired
  private mobilesecurityconfigurer mobilesecurityconfigurer;

  @override
  public void configure(httpsecurity http) throws exception {
    registry
        .antmatchers("/mobile/token").permissionall()
        .anyrequest().authenticated()
        .and()
        .csrf().disable();
    http.apply(mobilesecurityconfigurer);
  }
}

使用

复制代码 代码如下:

curl -h "authorization:basic cglnonbpzw==" -d "grant_type=mobile&scope=server&mobile=17034642119&code="

源码

请参考

基于spring cloud、spring security oauth2.0开发企业级认证与授权,提供常见服务监控、链路追踪、日志分析、缓存管理、任务调度等实现

整个逻辑是参考spring security 自身的 usernamepassword 登录模式实现,可以参考其源码。

验证码的发放、校验逻辑比较简单,方法后通过全局fiter 判断请求中code 是否和 手机号匹配集合,重点逻辑是令牌的参数

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网