现在手机验证码登录似乎是每个网站必备的功能,OAuth2支持扩展自定义授权模式,前面介绍了如何在系统集成短信通知服务,这里我们进行OAuth2的授权模式自定义扩展,使系统支持短信验证码登录。

1、在gitegg-oauth中新增SmsCaptchaTokenGranter 自定义短信验证码令牌授权处理类

/**
* 短信验证码模式
*/
public class SmsCaptchaTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "sms_captcha"; private final AuthenticationManager authenticationManager; private UserDetailsService userDetailsService; private IUserFeign userFeign; private ISmsFeign smsFeign; private RedisTemplate redisTemplate; private CaptchaService captchaService; private String captchaType; public SmsCaptchaTokenGranter(AuthenticationManager authenticationManager,
AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
OAuth2RequestFactory requestFactory, RedisTemplate redisTemplate, IUserFeign userFeign, ISmsFeign smsFeign, CaptchaService captchaService,
UserDetailsService userDetailsService, String captchaType) {
this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
this.redisTemplate = redisTemplate;
this.captchaService = captchaService;
this.captchaType = captchaType;
this.smsFeign = smsFeign;
this.userFeign = userFeign;
this.userDetailsService = userDetailsService;
} protected SmsCaptchaTokenGranter(AuthenticationManager authenticationManager,
AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
OAuth2RequestFactory requestFactory, String grantType) {
super(tokenServices, clientDetailsService, requestFactory, grantType);
this.authenticationManager = authenticationManager;
} @Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { Map<string, string=""> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
// 获取验证码类型
String captchaType = parameters.get(CaptchaConstant.CAPTCHA_TYPE);
// 判断传入的验证码类型和系统配置的是否一致
if (!StringUtils.isEmpty(captchaType) && !captchaType.equals(this.captchaType)) {
throw new UserDeniedAuthorizationException(ResultCodeEnum.INVALID_CAPTCHA_TYPE.getMsg());
}
if (CaptchaConstant.IMAGE_CAPTCHA.equalsIgnoreCase(captchaType)) {
// 图片验证码验证
String captchaKey = parameters.get(CaptchaConstant.CAPTCHA_KEY);
String captchaCode = parameters.get(CaptchaConstant.CAPTCHA_CODE);
// 获取验证码
String redisCode = (String)redisTemplate.opsForValue().get(CaptchaConstant.IMAGE_CAPTCHA_KEY + captchaKey);
// 判断验证码
if (captchaCode == null || !captchaCode.equalsIgnoreCase(redisCode)) {
throw new UserDeniedAuthorizationException(ResultCodeEnum.INVALID_CAPTCHA.getMsg());
}
} else {
// 滑动验证码验证
String captchaVerification = parameters.get(CaptchaConstant.CAPTCHA_VERIFICATION);
CaptchaVO captchaVO = new CaptchaVO();
captchaVO.setCaptchaVerification(captchaVerification);
ResponseModel responseModel = captchaService.verification(captchaVO);
if (null == responseModel || !RepCodeEnum.SUCCESS.getCode().equals(responseModel.getRepCode())) {
throw new UserDeniedAuthorizationException(ResultCodeEnum.INVALID_CAPTCHA.getMsg());
}
} String phoneNumber = parameters.get(TokenConstant.PHONE_NUMBER);
String smsCode = parameters.get(TokenConstant.SMS_CODE);
String code = parameters.get(TokenConstant.CODE);
// Protect from downstream leaks of password
parameters.remove(TokenConstant.CODE); Result<boolean> checkResult = smsFeign.checkSmsVerificationCode(smsCode, phoneNumber, code); if (null == checkResult || !checkResult.getData()) {
throw new InvalidGrantException(("Could not authenticate user: " + phoneNumber));
} UserDetails userDetails = this.userDetailsService.loadUserByUsername(phoneNumber); Authentication userAuth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
((AbstractAuthenticationToken)userAuth).setDetails(parameters); OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
return new OAuth2Authentication(storedOAuth2Request, userAuth);
} }

2、自定义GitEggTokenGranter,支持多种token模式

/**
* 自定义token
*/
public class GitEggTokenGranter { /**
* 自定义tokenGranter
*/
public static TokenGranter getTokenGranter(final AuthenticationManager authenticationManager,
final AuthorizationServerEndpointsConfigurer endpoints, RedisTemplate redisTemplate, IUserFeign userFeign,
ISmsFeign smsFeign, CaptchaService captchaService, UserDetailsService userDetailsService, String captchaType) {
// 默认tokenGranter集合
List<tokengranter> granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter()));
// 增加验证码模式
granters.add(new CaptchaTokenGranter(authenticationManager, endpoints.getTokenServices(),
endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), redisTemplate, captchaService,
captchaType));
// 增加短信验证码模式
granters.add(new SmsCaptchaTokenGranter(authenticationManager, endpoints.getTokenServices(),
endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), redisTemplate, userFeign, smsFeign, captchaService,
userDetailsService, captchaType));
// 组合tokenGranter集合
return new CompositeTokenGranter(granters);
} }

3、GitEggOAuthController中增加获取短信验证码的方法

    @ApiOperation("发送短信验证码")
@PostMapping("/sms/captcha/send")
public Result sendSmsCaptcha(@RequestBody SmsVerificationDTO smsVerificationDTO) {
Result<object> sendResult = smsFeign.sendSmsVerificationCode(smsVerificationDTO.getSmsCode(), smsVerificationDTO.getPhoneNumber());
return sendResult;
}

4、前端页面增加短信验证码登录方式

        <a-tab-pane key="phone_account" :tab="$t('user.login.tab-login-mobile')" class="color:#1890ff;">
<a-form-item>
<a-input size="large" type="text" :placeholder="$t('user.login.mobile.placeholder')" v-decorator="['phoneNumber', {rules: [{ required: true, pattern: /^1[34578]\d{9}$/, message: $t('user.phone-number.required') }], validateTrigger: 'change'}]">
<a-icon slot="prefix" type="mobile" :style="{ color: '#1890ff' }">
</a-icon></a-input>
</a-form-item> <a-row :gutter="16">
<a-col class="gutter-row" :span="16">
<a-form-item>
<a-input size="large" type="text" :placeholder="$t('user.login.mobile.verification-code.placeholder')" v-decorator="['captcha', {rules: [{ required: true, message: $t('user.verification-code.required') }], validateTrigger: 'blur'}]">
<a-icon slot="prefix" type="mail" :style="{ color: '#1890ff' }">
</a-icon></a-input>
</a-form-item>
</a-col>
<a-col class="gutter-row" :span="8">
<a-button class="getCaptcha" tabindex="-1" :disabled="state.smsSendBtn" @click.stop.prevent="getCaptcha" v-text="!state.smsSendBtn && $t('user.register.get-verification-code') || (state.time+' s')"></a-button>
</a-col>
</a-row>
</a-tab-pane>
getCaptcha (e) {
e.preventDefault()
const { form: { validateFields }, state } = this validateFields(['phoneNumber'], { force: true }, (err, values) => {
if (!err) {
state.smsSendBtn = true const interval = window.setInterval(() => {
if (state.time-- <= 0) {
state.time = 60
state.smsSendBtn = false
window.clearInterval(interval)
}
}, 1000) const hide = this.$message.loading('验证码发送中..', 0)
getSmsCaptcha({ phoneNumber: values.phoneNumber, smsCode: 'aliLoginCode' }).then(res => {
setTimeout(hide, 2500)
this.$notification['success']({
message: '提示',
description: '验证码获取成功,您的验证码为:' + res.result.captcha,
duration: 8
})
}).catch(err => {
setTimeout(hide, 1)
clearInterval(interval)
state.time = 60
state.smsSendBtn = false
this.requestFailed(err)
})
}
})
},
stepCaptchaSuccess () {
this.loginSuccess()
},
stepCaptchaCancel () {
this.Logout().then(() => {
this.loginBtn = false
this.stepCaptchaVisible = false
})
},

5、通过短信验证码登录界面

源码地址:

Gitee: https://gitee.com/wmz1930/GitEgg

GitHub: https://github.com/wmz1930/GitEgg

SpringCloud微服务实战——搭建企业级开发框架(二十六):自定义扩展OAuth2实现短信验证码登录的更多相关文章

  1. SpringCloud微服务实战——搭建企业级开发框架(十六):集成Sentinel高可用流量管理框架【自定义返回消息】

    Sentinel限流之后,默认的响应消息为Blocked by Sentinel (flow limiting),对于系统整体功能提示来说并不统一,参考我们前面设置的统一响应及异常处理方式,返回相同的 ...

  2. SpringCloud微服务实战——搭建企业级开发框架(十二):OpenFeign+Ribbon实现负载均衡

      Ribbon是Netflix下的负载均衡项目,它主要实现中间层应用程序的负载均衡.为Ribbon配置服务提供者地址列表后,Ribbon就会基于某种负载均衡算法,自动帮助服务调用者去请求.Ribbo ...

  3. SpringCloud微服务实战——搭建企业级开发框架(十):使用Nacos分布式配置中心

    随着业务的发展.微服务架构的升级,服务的数量.程序的配置日益增多(各种微服务.各种服务器地址.各种参数),传统的配置文件方式和数据库的方式已无法满足开发人员对配置管理的要求: 安全性:配置跟随源代码保 ...

  4. SpringCloud微服务实战——搭建企业级开发框架(十四):集成Sentinel高可用流量管理框架【限流】

      Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流.流量整形.熔断降级.系统负载保护.热点防护等多个维度来帮助开发者保障微服务的稳定性. Sentinel 具有 ...

  5. SpringCloud微服务实战——搭建企业级开发框架(十五):集成Sentinel高可用流量管理框架【熔断降级】

      Sentinel除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一.由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积.Sentinel ...

  6. SpringCloud微服务实战——搭建企业级开发框架(十九):Gateway使用knife4j聚合微服务文档

      本章介绍Spring Cloud Gateway网关如何集成knife4j,通过网关聚合所有的Swagger微服务文档 1.gitegg-gateway中引入knife4j依赖,如果没有后端代码编 ...

  7. SpringCloud微服务实战——搭建企业级开发框架(四十):使用Spring Security OAuth2实现单点登录(SSO)系统

    一.单点登录SSO介绍   目前每家企业或者平台都存在不止一套系统,由于历史原因每套系统采购于不同厂商,所以系统间都是相互独立的,都有自己的用户鉴权认证体系,当用户进行登录系统时,不得不记住每套系统的 ...

  8. SpringCloud微服务实战——搭建企业级开发框架(二十三):Gateway+OAuth2+JWT实现微服务统一认证授权

      OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段(具体什么手段OAuth2不关心)认证用户身份,并颁发token(令牌),使得第三方应用可以使用该token(令牌)在限定时间.限定 ...

  9. SpringCloud微服务实战——搭建企业级开发框架(四十七):【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能

      uni-app自带uni.request用于网络请求,因为我们需要自定义拦截器等功能,也是为了和我们后台管理保持统一,这里我们使用比较流行且功能更强大的axios来实现网络请求.   Axios ...

  10. SpringCloud微服务实战——搭建企业级开发框架(四十二):集成分布式任务调度平台XXL-JOB,实现定时任务功能

      定时任务几乎是每个业务系统必不可少的功能,计算到期时间.过期时间等,定时触发某项任务操作.在使用单体应用时,基本使用Spring提供的注解即可实现定时任务,而在使用微服务集群时,这种方式就要考虑添 ...

随机推荐

  1. OGG-如何只同步最近某个时间范围的数据

    一.需求,某客户希望使用OGG只同步时间大于2021-02-01日期之后的数据变换 需求如标题所示,如何使用OGG进行配置? 客户环境需要同步的表有几百G,表数据太大了;如果同步所有数据,目标库空间存 ...

  2. css3鼠标悬停图片边框线条动画特效

    css3鼠标经过内容区时,边框线条特效效果制作.   html: <div class="strength grWidth hidden"> <div class ...

  3. 【数据结构与算法Python版学习笔记】目录索引

    引言 算法分析 基本数据结构 概览 栈 stack 队列 Queue 双端队列 Deque 列表 List,链表实现 递归(Recursion) 定义及应用:分形树.谢尔宾斯基三角.汉诺塔.迷宫 优化 ...

  4. Beta Scrum Meeting汇总

    第0次Alpha Scrum Meeting 第1次Alpha Scrum Meeting 第2次Alpha Scrum Meeting 第3次Alpha Scrum Meeting 第4次Alpha ...

  5. BUAA2020软工作业(五)——软件案例分析

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件案例分析作业 我在这个课程的目标是 进一步提高自己的编码能力,工程能力 这个作业在哪个具体方面 ...

  6. 使用json-path解析json

    在我们的日常开发中,有时候需要从一个json字符串中获取一个值,或者从一段json字符串中获取到某些值,如果先使用Gson或Jackson转换成java对象在获取值,有些时候是很麻烦的,那么有没有一种 ...

  7. Photoshop cc 绿色版 最新版 下载

    Photoshop cc 绿色版 下载 Photoshop cc 绿色版 最新版下载百度网盘下载 Photoshop 下载提取码: dh6z 作为一个程序员, 不懂点基本的作图都不配"新时代 ...

  8. Veritas Backup Exec™ 21.3 Multilingual (Windows)

    Backup Exec 21.3, Release date: 2021-09-06 请访问原文链接:https://sysin.org/blog/veritas-backup-exec-21-3/, ...

  9. 升级 dubbo 小心 default.version

    上周遇到个关于升级dubbo 2.6 到2.7的兼容性问题,差点造成线上故障,这里记录下,也给大家提个醒. 问题回放 有一个接口的提供方(dubbo 2.6.6)这么配置接口的版本号 <dubb ...

  10. Java 在PPT中创建散点图

    本文将以Java代码示例展示如何在PPT幻灯片中创建散点图表. 创建图表前 需要在Java程序中导入用于操作PPT的jar包 Free Spire.Presentation for Java.可参考如 ...