A. 概述
首先明确一下目标:做一个通过手机验证找回(修改)账户密码的功能,例如:
流程大致如下:
1)用户输入手机号码
2)点击获取验证码(这时候前端有一些任务,如验证手机号格式,时间倒计时,按钮状态等等,这里只记录java部分)
3)后台验证手机号码是否属于且只属于某个账户,如果是生成验证码发送给该手机号并保存验证码、手机号、发送时间、有效时间为一条验证记录到数据库中等待验证
4)用户收到信息并将验证码输入,填写新密码后点击确认
5)后台验证用户提交的验证记录是否存在,如果存在,修改密码
这里记录的是后台的这两个接口。
B. 准备工作
a. 阿里云短信服务账户,AccessKey、短信模板、短信签名等,还需要在账户中存一点点钱或者买短信包。
b. 阿里云短信官方API 短信服务 > API参考 > 发送短信 > SendSms
C. 实现
依赖:<!-- 阿里云验证码使用SDK --><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.0</version></dependency>
配置信息: 获取验证码接口:
@PreAuthorize("@el.check('anonymous')")@GetMapping("/sendMsg/{phone}")public String sendMsg(@PathVariable("phone") String phone) {// TODO 查找验证表中是否有当前手机号(如果系统有多种业务还要看当前业务)是否有仍在有效期的验证码记录String code;DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, secret);IAcsClient client = new DefaultAcsClient(profile);CommonRequest request = new CommonRequest();request.setSysMethod(MethodType.POST);request.setSysDomain("");request.setSysVersion("-05-25");request.setSysAction("SendSms");request.putQueryParameter("RegionId", "cn-hangzhou");request.putQueryParameter("PhoneNumbers", phone);request.putQueryParameter("SignName", "——————");// 短信签名的名称request.putQueryParameter("TemplateCode", "——————");// 短信模板的模板CODE,格式大概是 SMS_***if( /* 验证表中存在当前手机号(当前业务)仍在有效期的验证码记录 */) {try {code = RandomUtil.randomNumbers(6);// 生成新的六位验证码request.putQueryParameter("TemplateParam", "{\"code\": \"" + code + "\"}");CommonResponse response = client.getCommonResponse(request); // 发送短信JSONObject resp = JSON.parseObject(response.getData());if (resp.get("Code").toString().equals("OK") && resp.get("Message").toString().equals("OK")) {// 发送成功// TODO 保存验证码记录至数据库,包括手机号、验证码、(业务类型、)发送时间、有效时间return "success";}} catch (ClientException e) {e.printStackTrace();}} else {// 如果有记录就不用生成新的验证码try {code = /* 从记录中获取code */;request.putQueryParameter("TemplateParam", "{\"code\": \"" + code + "\"}");CommonResponse response = client.getCommonResponse(request); // 发送短信JSONObject resp = JSON.parseObject(response.getData());if (resp.get("Code").toString().equals("OK") && resp.get("Message").toString().equals("OK")) {// 也不需要保存记录return "success";}} catch (ClientException e) {e.printStackTrace();}}return "failed";}
提交修改密码接口:
@PreAuthorize("@el.check('anonymous')")@PostMapping(value = "/findPass")public ResponseEntity findPass(@RequestBody Map<String, String> params){// TODO 根据params中的手机号、验证码(以及当前业务)和当前时间查找验证表是否有记录// TODO 如果存在,可以修改账户密码return new ResponseEntity(HttpStatus.OK);}