1.注冊(cè)流程分析
客戶端先發(fā)送一個(gè)手機(jī)號(hào)碼到后端獲取驗(yàn)證碼财破,此時(shí)“獲取驗(yàn)證碼”按鈕是激活狀態(tài)嘁酿,“下一步”按鈕是禁用狀態(tài)
點(diǎn)擊“獲取驗(yàn)證碼”按鈕咸包,該按鈕60秒倒計(jì)時(shí)變?yōu)榻脿顟B(tài),等待用戶接收驗(yàn)證碼并輸入
后端根據(jù)這個(gè)手機(jī)號(hào)先到數(shù)據(jù)庫(kù)查詢?cè)撌謾C(jī)號(hào)是否已被注冊(cè)闪唆,如果已經(jīng)被注冊(cè)就返回“該手機(jī)號(hào)已被注冊(cè)”,不繼續(xù)后續(xù)步驟
如果沒(méi)被注冊(cè),后端為該手機(jī)號(hào)生成一個(gè)隨機(jī)6位驗(yàn)證碼存在Redis中(指定時(shí)限),然后將該驗(yàn)證碼通過(guò)阿里云的短信服務(wù)接口發(fā)送給客戶端
客戶端收到短信徒探,輸入驗(yàn)證碼,點(diǎn)擊下一步
后端收到客戶端發(fā)送的驗(yàn)證碼喂窟,就將其和Redis中暫存的驗(yàn)證碼比對(duì)测暗,如果一致就放行央串,否則提示“驗(yàn)證碼錯(cuò)誤”
驗(yàn)證碼正確,進(jìn)入填寫密碼的頁(yè)面碗啄,填寫完畢提交到后端质和,加密存入數(shù)據(jù)庫(kù),注冊(cè)成功稚字,讓用戶選擇去登錄饲宿,還是回到首頁(yè)
2.Redis準(zhǔn)備
解壓后放入本地目錄
運(yùn)行運(yùn)行redis-server
cdD:\tools\redisredis-server.exeredis.windows.conf
image.png
再開一個(gè)命令行窗口,進(jìn)入redis目錄胆描,運(yùn)行redis-cli.exe命令瘫想,進(jìn)行一下基本操作
set是設(shè)置鍵值對(duì),keys是列出所有鍵昌讲,get是獲取指定鍵的值国夜,del是刪除指定的鍵值
image.png
3. 阿里云短信服務(wù)
demo程序,注意修改其中***的內(nèi)容為自己的
package com.soft1721.jianyue.api.util;importcom.aliyuncs.CommonRequest;importcom.aliyuncs.CommonResponse;importcom.aliyuncs.DefaultAcsClient;importcom.aliyuncs.IAcsClient;importcom.aliyuncs.exceptions.ClientException;importcom.aliyuncs.exceptions.ServerException;importcom.aliyuncs.http.MethodType;importcom.aliyuncs.profile.DefaultProfile;/**
* 短消息測(cè)試程序
*/publicclassSMSTest{publicstaticvoidmain(String[] args){? ? ? ? DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou","*******","*****");? ? ? ? IAcsClient client =newDefaultAcsClient(profile);? ? ? ? CommonRequest request =newCommonRequest();? ? ? ? request.setMethod(MethodType.POST);? ? ? ? request.setDomain("dysmsapi.aliyuncs.com");? ? ? ? request.setVersion("2017-05-25");? ? ? ? request.setAction("SendSms");? ? ? ? request.putQueryParameter("RegionId","cn-hangzhou");? ? ? ? request.putQueryParameter("PhoneNumbers","****");? ? ? ? request.putQueryParameter("SignName","****");? ? ? ? request.putQueryParameter("TemplateCode","SMS_135805735");? ? ? ? request.putQueryParameter("TemplateParam","{\"code\":\"888888\"}");try{? ? ? ? ? ? CommonResponse response = client.getCommonResponse(request);? ? ? ? ? ? System.out.println(response.getData());? ? ? ? }catch(ServerException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }catch(ClientException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? }}
image.png
4.后端
pom.xml剧蚣,增加阿里云短信服務(wù)SDK依賴和SpringBoot集成redis依賴
com.aliyunaliyun-java-sdk-core4.0.3org.springframework.bootspring-boot-starter-data-redis
util包的StringUtil類增加一個(gè)方法支竹,用來(lái)獲取六位隨機(jī)數(shù)驗(yàn)證碼
publicstaticStringgetVerifyCode(){? ? Random random =newRandom();? ? StringBuilder stringBuilder =newStringBuilder();for(inti =0; i <6; i++) {? ? ? ? stringBuilder.append(String.valueOf(random.nextInt(10)));? ? }returnstringBuilder.toString();}
編寫SMSUtil短信發(fā)送工具類,主要將手機(jī)號(hào)和短信字符串分離成變量鸠按,main方法測(cè)試通過(guò)后即可刪除
importcom.aliyuncs.CommonRequest;importcom.aliyuncs.CommonResponse;importcom.aliyuncs.DefaultAcsClient;importcom.aliyuncs.IAcsClient;importcom.aliyuncs.exceptions.ClientException;importcom.aliyuncs.exceptions.ServerException;importcom.aliyuncs.http.MethodType;importcom.aliyuncs.profile.DefaultProfile;/**
* 短信發(fā)送工具類,返回生成的隨機(jī)驗(yàn)證碼
*/publicclassSMSUtil{publicstaticStringsend(String mobile){? ? ? ? DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou","*******","*******");? ? ? ? IAcsClient client =newDefaultAcsClient(profile);? ? ? ? CommonRequest request =newCommonRequest();? ? ? ? request.setMethod(MethodType.POST);? ? ? ? request.setDomain("dysmsapi.aliyuncs.com");? ? ? ? request.setVersion("2017-05-25");? ? ? ? request.setAction("SendSms");? ? ? ? request.putQueryParameter("RegionId","cn-hangzhou");? ? ? ? request.putQueryParameter("PhoneNumbers", mobile);? ? ? ? request.putQueryParameter("SignName","*****");? ? ? ? request.putQueryParameter("TemplateCode","SMS_135805735");? ? ? ? String verifyCode = StringUtil.getVerifyCode();? ? ? ? request.putQueryParameter("TemplateParam","{\"code\":"+ verifyCode +"}");try{? ? ? ? ? ? CommonResponse response = client.getCommonResponse(request);? ? ? ? ? ? System.out.println(response.getData());? ? ? ? }catch(ServerException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }catch(ClientException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }returnverifyCode;? ? }publicstaticvoidmain(String[] args){? ? ? ? System.out.println(send("139****1489"));? ? }}
mapper層增加insertUser方法饶碘,自行實(shí)現(xiàn)(id和token不用給值)
service接口增加注冊(cè)方法
voidsignUp(UserDTO userDTO);
signUp方法實(shí)現(xiàn)代碼
@OverridepublicvoidsignUp(UserDTO userDTO){? ? User user1 =newUser();? ? user1.setMobile(userDTO.getMobile()); user1.setPassword(StringUtil.getBase64Encoder(userDTO.getPassword()));? ? user1.setNickname("新用戶"); user1.setAvatar("http://ppeto2k90.bkt.clouddn.com/avatar/default.png");? ? user1.setRegtime(newDate());? ? user1.setStatus((short)1);? ? userMapper.insert(user1);}
單元測(cè)試
@TestpublicvoidsignUp(){? ? UserDTO userDTO =newUserDTO();? ? userDTO.setMobile("139****1489");? ? userDTO.setPassword("111");? ? userService.signUp(userDTO); }
controller層編寫前目尖,先到StatusConst和MsgConst添加需要用到的常量
publicstaticfinalintMOBILE_EXIST =5;publicstaticfinalintVERIFYCODE_ERROR =6;
publicstaticfinalString MOBILE_EXIST ="手機(jī)號(hào)已被注冊(cè)";publicstaticfinalString VERIFYCODE_ERROR ="驗(yàn)證碼錯(cuò)誤";
獲取短信驗(yàn)證碼接口
@PostMapping(value ="/verify")publicResponseResultgetVerifyCode(@RequestParam("mobile")String mobile){? ? ? ? User user = userService.getUserByMobile(mobile);//手機(jī)號(hào)已經(jīng)被注冊(cè)if(user !=null) {returnResponseResult.error(StatusConst.MOBILE_EXIST, MsgConst.MOBILE_EXIST);? ? ? ? }else{//發(fā)送驗(yàn)證碼String verifyCode = SMSUtil.send(mobile);//? ? ? ? ? ? String verifyCode = StringUtil.getVerifyCode();System.out.println(verifyCode);//手機(jī)號(hào)和驗(yàn)證碼作為鍵值對(duì)存入redis中redisService.set(mobile, verifyCode);returnResponseResult.success();? ? ? ? }? ? }
驗(yàn)證短信碼接口
@PostMapping(value ="/check")public ResponseResult checkVerifyCode(@RequestParam("mobile") String mobile, @RequestParam("verifyCode") String verifyCode) {//從Redis中取出這個(gè)手機(jī)號(hào)的驗(yàn)證碼? ? String code = redisService.get(mobile).toString();//System.out.println(code +"---");//System.out.println(verifyCode);//和客戶端傳過(guò)來(lái)的驗(yàn)證碼比對(duì)if(code.equals(verifyCode)) {returnResponseResult.success();? ? }else{returnResponseResult.error(StatusConst.VERIFYCODE_ERROR, MsgConst.VERIFYCODE_ERROR);? ? }}
注冊(cè)接口