前端功能问题系列文章,点击上方合集↑
序言
大家好,我是大澈!
本文约3400+字,整篇阅读大约需要4分钟。
本文主要内容分三部分,第一部分是需求分析,第二部分是实现步骤,第三部分是问题详解。
如果您只需要解决问题,请阅读第一、二部分即可。
如果您有更多时间,进一步学习问题相关知识点,请阅读至第三部分。
1. 需求分析
点击发送验证码按钮,获取手机短信验证码。此时,发送验证码按钮进入倒计时状态,且不可被点击。
成功获取到短信验证码并输入,点击登录按钮,完成页面跳转。
2. 实现步骤 2.1 准备工作
短信验证码登录功能的实现,借助了阿里云短信业务API,我们可以使用阿里云的短信服务向用户发送验证码、通知、营销等不同类型的短信。
总体实现步骤如下:
下面是具体的代码实现,包括前端、后端两方面。
2.2编写前端代码
对于前端来说,所做的操作并不算多,无非是要实现点击发送短信验证码后的倒计时效果,以及两个接口的调用。
对于倒计时效果,就是利用了定时器,去控制发送验证码按钮的状态。
对于调用的两个接口,一个是发送短信接口,一个是短信验证及登录接口。
相关代码实例请继续往下看,每个地方基本都给大家做了详细的注释。
模版代码:
0"> {{ countdown > 0 ? `重新发送(${countdown})` : '发送验证码' }} 登录
逻辑代码:
import {reactive, ref} from 'vue'import Axios from '../api/axios';import {ElMessage} from "element-plus";const dataForm = reactive({ phone: '123456', code: '',})let isSendingCode = ref(false);let countdown = ref(0);// 发送验证码,调验证码接口const sendVerificationCode = () => { // 检查手机号是否有效 // ... // 调发送短信接口 Axios.get('/admin/send', { params: { phone: dataForm.phone, } }) .then(res => { ElMessage.success(res.data) }) .catch(error => { console.error(error); }); isSendingCode.value = true; // 设置倒计时时间,这里假设为10秒 countdown.value = 10; // 倒计时效果 const countdownInterval = setInterval(() => { countdown.value--; if (countdown.value { // 调发送短信接口 Axios.post('/admin/checkLogin', { phoneNumber: dataForm.phone, code: dataForm.code, }) .then(res => { ElMessage.success(res.data) }) .catch(error => { console.error(error); });}
2.3编写后端接口
对于后端实现,要先引入阿里云短信业务依赖,再封装短信发送工具类,再编写两个接口,一个是发送短信接口,一个是短信验证及登录接口。
在发送短信接口业务层中,生成随机字符串,传入并调用短信发送工具类方法发送验证码,并把验证码存入Redis中。
在短信验证及登录接口业务层中,将前端传过来的验证码与Redis中存的验证码进行比较,校验成功执行下一步登录操作。
相关代码实例请继续往下看,每个地方基本都给大家做了详细的注释。
Pom.xml中引入依赖代码:
org.springframework.boot spring-boot-starter-data-redis com.aliyun aliyun-java-sdk-core 4.6.0 com.aliyun aliyun-java-sdk-dysmsapi 1.1.0 com.alibaba fastjson 1.2.76
短信发送服务工具类代码:
package com.dache.base.common.util;import com.alibaba.fastjson.JSONObject;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.exceptions.ServerException;import com.aliyuncs.profile.DefaultProfile;import com.google.gson.Gson;import java.util.HashMap;/** * @Description 短信发送服务 */public class SmsUtil { public static String toSendMes(String phoneNumber,String code) { //1.连接阿里云 /** "", // The region ID 地区标识 "", // The AccessKey ID of the RAM account RAM账户的AccessKey ID 阿里云账号可查 "", // The AccessKey Secret of the RAM account RAM 账户的 AccessKey Secret 阿里云账号可查 **/ DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", "your-access-key-id", "your-access-key-secret"); IAcsClient client = new DefaultAcsClient(profile); //2.构建请求 自定义参数 SendSmsRequest request = new SendSmsRequest(); //接收短信的手机号码 request.setPhoneNumbers(phoneNumber); //短信签名名称 request.setSignName("阿里云短信测试"); //短信模板CODE request.setTemplateCode("SMS_154SECRET9"); //模版内容:您正在使用阿里云短信测试服务,体验验证码是:${code},如非本人操作,请忽略本短信! //短信模板变量对应的实际值 //("{"code":"1234"}"); HashMap param=new HashMap(); param.put("code",code); request.setTemplateParam(JSONObject.toJSONString(param)); SendSmsResponse response = new SendSmsResponse(); try { //3.发送请求 response = client.getAcsResponse(request); } catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) { System.out.println("ErrCode:" + e.getErrCode()); System.out.println("ErrMsg:" + e.getErrMsg()); System.out.println("RequestId:" + e.getRequestId()); } //短信成功返回json { "RequestId": "614048FB-0619-4439-A1D5-AA8B218A****", "Message": "OK", "BizId": "386715418801811068^0", "Code": "OK"} return response.getMessage(); }}
接口Controller层代码:
/*** 发送短信*/@ApiOperation(value = "发送短信")@GetMapping("/send")public CommonResult toSendMessage(@RequestParam("phone") String phone){ String message = adminService.toSendMessage(phone); return CommonResult.success(message);}/*** 检验验证码和密码,校验成功后登录*/@ApiOperation(value = "检验验证码和密码,校验成功后登录")@PostMapping("/checkLogin")public CommonResult checkLogin(@RequestBody ToCheckLoginDTO toCheckLogin){ String checkLogin = adminService.checkLogin(toCheckLogin.getPhoneNumber(), toCheckLogin.getCode()); // 省略用户密码加密校验 // ... // 省略JWT认证 // ... return CommonResult.success(checkLogin);}
接口Service层代码:
/*** 发送短信*/@Overridepublic String toSendMessage(String phoneNumber) { //扩展 可以验证该电话号码是否注册 //1.判定验证码是否过期 String code = redisTemplate.opsForValue().get(phoneNumber); if (!StringUtils.isEmpty(code)){ return phoneNumber+":"+"验证码未过期"; } //2.已过期/无验证码 生成验证码 //随机生成字符串 做验证码 int toCode = (int) (Math.random() * (50000 - 40000) + 40000); code=Integer.toString(toCode); String toSendMes = SmsUtil.toSendMes(phoneNumber, code); if (ComConstants.OK.equals(toSendMes)){ //redis 中存放 5分钟过期 redisTemplate.opsForValue().set(phoneNumber,code,ComConstants.NUM_FIVE, TimeUnit.MINUTES); //3.发送短信 return "短信发送成功"; } return "短信发送异常";}/*** 检验手机验证码并登录*/@Overridepublic String checkLogin(String phoneNumber, String code) { //1.redis 验证码校验 String redisCode = redisTemplate.opsForValue().get(phoneNumber); if (code.equals(redisCode)){ return "登入成功"; } return "登入失败";}
当然,上述前端和后端代码的实现中,必然会存在一些缺陷,因为它只是一个实例,具体的实现还需要在项目中根据需求进行完善。
3. 问题详解 3.1 常见短信服务API文档地址整理
阿里云短信服务API文档地址:。
以下是一些其它常见短信服务供应商:
结语
建立这个平台的初衷:
原创文章,作者:筱凯,如若转载,请注明出处:https://www.jingyueyun.com/ask/915.html