13Redis--手机验证码功能--阿里云实现 -- 删除

目录

Redis实现手机验证码

9.1、实现原理

9.2、实现

1、校验手机号是否合法的工具类

2、生成验证码的工具类

3、短信微服务Controller

4、短信微服务Service层

5、用户注册微服务Controller

6、用户注册微服务Service

9.3、测试

1、使用短信微服务向指定手机号发送验证码

2、查看Redis缓存和短信

3、打开用户中心微服务进行测试

4、结果


Redis实现手机验证码----未完成

了解阿里云的用户权限操作

1、开启子用户

2、新建一个用户组(设置添加权限sms)

3、创建一个用户(具体用来操作的账号)

4、得到AccessKey(id,密码) 

开通阿里云短信服务

9.1、实现原理

  • 使用工具类生成4位或6位的数字验证码
  • 校验手机号为合法后通过短信微服务发送验证码
  • 将手机号作为key,验证码作为value存入redis中,并设置一个过期时间
  • 用户进行登录/注册时通过key(手机号)到redis中取出验证码
  • 进行验证码比对,若匹配则登录/注册通过,随机删除redis中的key-value

9.2、实现

1、校验手机号是否合法的工具类

 
  1. public class FormUtils {
  2. private static Pattern NUMBER_PATTERN = Pattern.compile("^[1][3,4,5,7,8,9][0-9]{9}$");
  3. /**
  4. * 手机号验证
  5. */
  6. public static boolean isMobile(String str) {
  7. //验证手机号的正则表达式
  8. return NUMBER_PATTERN.matcher(str).matches();
  9. }
  10. }

2、生成验证码的工具类

 
  1. public class RandomUtils {
  2. private static final Random random = new Random();
  3. private static final DecimalFormat fourdf = new DecimalFormat("0000");
  4. private static final DecimalFormat sixdf = new DecimalFormat("000000");
  5. public static String getFourBitRandom() {
  6. return fourdf.format(random.nextInt(10000));
  7. }
  8. public static String getSixBitRandom() {
  9. return sixdf.format(random.nextInt(1000000));
  10. }
  11. /**
  12. * 给定数组,抽取n个数据
  13. * @param list
  14. * @param n
  15. * @return
  16. */
  17. public static ArrayList getRandom(List list, int n) {
  18. Random random = new Random();
  19. HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
  20. // 生成随机数字并存入HashMap
  21. for (int i = 0; i < list.size(); i++) {
  22. int number = random.nextInt(100) + 1;
  23. hashMap.put(number, i);
  24. }
  25. // 从HashMap导入数组
  26. Object[] robjs = hashMap.values().toArray();
  27. ArrayList r = new ArrayList();
  28. // 遍历数组并打印数据
  29. for (int i = 0; i < n; i++) {
  30. r.add(list.get((int) robjs[i]));
  31. System.out.print(list.get((int) robjs[i]) + "\t");
  32. }
  33. System.out.print("\n");
  34. return r;
  35. }
  36. }

3、短信微服务Controller

 
  1. @Slf4j
  2. @CrossOrigin
  3. @RestController
  4. @Api(tags = "短信管理控制器")
  5. @RequestMapping("/api/sms")
  6. public class ApiSmsController {
  7. @Autowired
  8. private SmsService smsService;
  9. @Autowired
  10. private RedisTemplate redisTemplate;
  11. /***
  12. * 根据传入的手机号来生成并发送验证码
  13. * 并将验证码存入redis缓存
  14. * @param mobile 手机号
  15. * @return
  16. */
  17. @GetMapping("send/{mobile}")
  18. @ApiOperation("一个用于生成验证码,并将验证码存入redis中的接口")
  19. public R getCode(@PathVariable("mobile") String mobile) throws ClientException {
  20. //0 校验手机号是否合法
  21. if(StringUtils.isBlank(mobile) || !FormUtils.isMobile(mobile)) {
  22. //如果手机号为空或手机号不合法
  23. log.error("手机号不合法!");
  24. // new GrainException(ResultCodeEnum.LOGIN_MOBILE_ERROR);
  25. return R.error().message("手机号不正确!").code(28001);
  26. }
  27. //1 使用工具类生成生成验证码
  28. String checkCode = RandomUtils.getSixBitRandom();
  29. //2 发送验证码
  30. smsService.send(mobile,checkCode);
  31. //3 存储验证码到redis
  32. //使用redisTemplate,使用手机号作为键,保存时长为5分钟
  33. redisTemplate.opsForValue().set(mobile,checkCode,5, TimeUnit.MINUTES);
  34. return R.ok().message("短信发送成功!");
  35. }
  36. }

4、短信微服务Service层

 
  1. @Slf4j
  2. @Service
  3. public class SmsServiceImpl implements SmsService {
  4. @Autowired
  5. private SmsProperties smsProperties;
  6. @Override
  7. public void send(String mobile, String checkCode) throws ClientException, ClientException {
  8. //调用短信发送SDK,创建client对象
  9. DefaultProfile profile = DefaultProfile.getProfile(
  10. smsProperties.getRegionId(),
  11. smsProperties.getKeyId(),
  12. smsProperties.getKeySecret());
  13. IAcsClient client = new DefaultAcsClient(profile);
  14. //组装请求参数
  15. CommonRequest request = new CommonRequest();
  16. request.setSysMethod(MethodType.POST);
  17. request.setSysDomain("dysmsapi.aliyuncs.com");
  18. request.setSysVersion("2017-05-25");
  19. request.setSysAction("SendSms");
  20. request.putQueryParameter("RegionId", smsProperties.getRegionId());
  21. request.putQueryParameter("PhoneNumbers", mobile);
  22. request.putQueryParameter("SignName", smsProperties.getSignName());
  23. request.putQueryParameter("TemplateCode", smsProperties.getTemplateCode());
  24. Map<String, Object> param = new HashMap<>();
  25. param.put("code", checkCode);
  26. //将包含验证码的集合转换为json字符串
  27. Gson gson = new Gson();
  28. request.putQueryParameter("TemplateParam", gson.toJson(param));
  29. //发送短信
  30. CommonResponse response = client.getCommonResponse(request);
  31. //得到json字符串格式的响应结果
  32. String data = response.getData();
  33. //解析json字符串格式的响应结果
  34. HashMap<String, String> map = gson.fromJson(data, HashMap.class);
  35. String code = map.get("Code");
  36. String message = map.get("Message");
  37. //配置参考:短信服务->系统设置->国内消息设置
  38. //错误码参考:
  39. //https://help.aliyun.com/document_detail/101346.html?spm=a2c4g.11186623.6.613.3f6e2246sDg6Ry
  40. //控制所有短信流向限制(同一手机号:一分钟一条、一个小时五条、一天十条)
  41. if ("isv.BUSINESS_LIMIT_CONTROL".equals(code)) {
  42. log.error("短信发送过于频繁 " + "【code】" + code + ", 【message】" + message);
  43. throw new GrainException(ResultCodeEnum.SMS_SEND_ERROR_BUSINESS_LIMIT_CONTROL);
  44. }
  45. if (!"OK".equals(code)) {
  46. log.error("短信发送失败 " + " - code: " + code + ", message: " + message);
  47. throw new GrainException(ResultCodeEnum.SMS_SEND_ERROR);
  48. }
  49. }
  50. }

5、用户注册微服务Controller

 
  1. @Slf4j
  2. @CrossOrigin
  3. @RestController
  4. @Api(tags = "会员管理控制器")
  5. @RequestMapping("/api/ucenter/member")
  6. public class ApiMemberController {
  7. @Autowired
  8. private MemberService memberService;
  9. @ApiOperation("会员注册")
  10. @PostMapping("register")
  11. public R register(@RequestBody RegisterVo registerVo) {
  12. memberService.register(registerVo);
  13. return R.ok().message("注册成功!");
  14. }
  15. }

6、用户注册微服务Service

 
  1. @Service
  2. public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
  3. @Autowired
  4. private RedisTemplate redisTemplate;
  5. @Autowired
  6. private MemberMapper memberMapper;
  7. @Override
  8. public void register(RegisterVo registerVo) {
  9. String nickname = registerVo.getNickname();
  10. String mobile = registerVo.getMobile();
  11. String code = registerVo.getCode();
  12. String password = registerVo.getPassword();
  13. if(StringUtils.isBlank(mobile) || !FormUtils.isMobile(mobile)) {
  14. throw new GrainException(ResultCodeEnum.LOGIN_MOBILE_ERROR);
  15. }
  16. if(StringUtils.isBlank(nickname) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
  17. throw new GrainException(ResultCodeEnum.PARAM_ERROR);
  18. }
  19. //校验验证码
  20. String checkCode = (String)redisTemplate.opsForValue().get(mobile);
  21. if(!StringUtils.equals(code,checkCode)) {
  22. //如果用户输入验证码和redis中验证码不相等
  23. //校验失败
  24. throw new GrainException(ResultCodeEnum.CODE_ERROR);
  25. }
  26. //判断用户手机号是否注册
  27. QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
  28. memberQueryWrapper.eq("mobile",mobile);
  29. Integer result = memberMapper.selectCount(memberQueryWrapper);
  30. if(result > 0) {
  31. throw new GrainException(ResultCodeEnum.REGISTER_MOBLE_ERROR);
  32. }
  33. //注册
  34. Member member = new Member();
  35. member.setNickname(nickname);
  36. member.setMobile(mobile);
  37. //密码需要加密
  38. member.setPassword(MD5.encrypt(password));
  39. member.setAvatar("http://tiebapic.baidu.com/forum/w%3D580/sign=21e19fd45010b912bfc1f6f6f3fcfcb5/c0d5d04b20a44623e5077d0d8f22720e0ef3d78e.jpg");
  40. member.setDisabled(false);
  41. memberMapper.insert(member);
  42. //将redis缓存中的验证码删除
  43. redisTemplate.delete(mobile);
  44. }
  45. }

9.3、测试

启动短信微服务和用户注册微服务,使用Swagger进行测试

1、使用短信微服务向指定手机号发送验证码

正在上传…重新上传取消

2、查看Redis缓存和短信

短信

3、打开用户中心微服务进行测试

4、结果

swagger提示注册成功

redis缓存中该键值对被删除

数据库

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gh-xiaohe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值