SpringBoot OAuth2.0 使用短信验证码登录授权

SpringBoot OAuth2.0 使用短信验证码登录授权

实现步骤:

  • 自定义授权器,继承 AbstractTokenGranter 类;
  • 重写 getOAuth2Authentication 函数,在这个函数中,自定义授权认证逻辑;
  • 校验手机号 + 短信验证码是否一致
  • getOAuth2Authentication, 手机和验证码校验无误, 返回 OAuth2Authentication 授权信息(access_token)

创建 SmsCodeTokenGranter 继承 AbstractTokenGranter

public class SmsCodeTokenGranter extends AbstractTokenGranter {
  private static final String SMS_GRANT_TYPE = "sms_code";

  private AccountService accountService;

  public SmsCodeTokenGranter(AuthorizationServerTokenServices tokenServices,
      ClientDetailsService clientDetailsService,
      OAuth2RequestFactory requestFactory) {
    super(tokenServices, clientDetailsService, requestFactory, SMS_GRANT_TYPE);
  }

  public void setAccountService(AccountService accountService) {
    this.accountService = accountService;
  }

  @Override
  protected OAuth2Authentication getOAuth2Authentication(ClientDetails client,
      TokenRequest tokenRequest) {

    Map<String, String> parameters =
        new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());

    // 客户端提交的手机号码
    String phoneNumber = parameters.get(CommonConstant.DEFAULT_PARAMETER_NAME_PHONE);
    if (StringUtils.isBlank(phoneNumber)) {
      throw new BusinessException(ResultCode.PHONE_NUMBER_IS_EMPTY);
    }

    // 客户端提交的验证码
    String smsCode = parameters.get(CommonConstant.DEFAULT_PARAMETER_NAME_CODE_SMS);
    if (!smsCode.equals("9876")) {
      throw new BusinessException(ResultCode.SMS_CODE_ERROR);
    }

    // 客户端提交的手机号码
    AccountDTO accountDTO = accountService.getAccountByPhone(phoneNumber);

    // TODO: if account not exist , create a new account ??
    if (ObjectUtils.isEmpty(accountDTO)) {
      throw new BusinessException(ResultCode.PHONE_NOT_EXITS);
    }

    // TODO: 权限查询 etc...
    RoleDTO role = new RoleDTO();
    role.setRole("USER");
    //accountService.getAccountRole(accountDTO.getAccountId());

    // 根据手机号码查询用户 ...

    List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole()));
    UserDetails user = new MooseUserDetails(accountDTO, null, grantedAuthorities);

    // 验证用户状态(是否禁用 etc...)

    Authentication userAuth =
        new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
    // org.springframework.security.core.userdetails.UserDetails 接口的, 所以有 user.getAuthorities()
    // 当然该参数传null也行
    ((AbstractAuthenticationToken) userAuth).setDetails(parameters);
    OAuth2Request storedOAuth2Request =
        getRequestFactory().createOAuth2Request(client, tokenRequest);
    return new OAuth2Authentication(storedOAuth2Request, userAuth);
  }
}

在 MooseAuthorizationServerConfiguration 添加授权类型
/**
   * 添加自定义授权类型
   *
   * @return List<TokenGranter>
   */
  private TokenGranter tokenGranter(final AuthorizationServerEndpointsConfigurer endpoints) {
      
      // endpoints.getTokenGranter() 获取SpringSecurity OAuth2.0 现有的授权类型
    List<TokenGranter> granters =
        new ArrayList<TokenGranter>(Collections.singletonList(endpoints.getTokenGranter()));

      // 构建短信验证授权类型
    SmsCodeTokenGranter smsCodeTokenGranter =
        new SmsCodeTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),
            endpoints.getOAuth2RequestFactory());
    smsCodeTokenGranter.setAccountService(accountService);
      // 向集合中添加短信授权类型
    granters.add(smsCodeTokenGranter);
      // 返回所有类型
    return new CompositeTokenGranter(granters);
  }
在 MooseAuthorizationServerConfiguration configure 添加所有端点信息
/**
   * Authorization Server endpoints.
   *
   * @throws Exception
   */
  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
        .tokenGranter(tokenGranter(endpoints))
        .tokenStore(tokenStore())
        .exceptionTranslator(customOAuth2ResponseExceptionTranslator);

    // 用于支持密码模式
    endpoints.authenticationManager(authenticationManager);

    // userDetailsService refresh_token
    endpoints.userDetailsService(userDetailsService);
  }

启动服务测试

grant_type:sms_code
client_id:client
client_secret:secret
phone:1537031501
smsCode:9876

localhost:7000/oauth/token?grant_type=sms_code&client_id=client&client_secret=secret&phone=1537031501&smsCode=9876

短信验证码输入错误

短信验证码和手机号码都输入正确

携带 access_token 访问接口

关注公众号 「全栈技术部」,不断学习更多有趣的技术知识。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值