谷粒商城----认证服务

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 谷粒商城----认证服务

一、短信验证码(阿里云短信服务)

@Data
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
@Component
public class SmsComponent {
  private String host;
  private String path;
  private String skin;
  private String sign;
  private String appCode;
  public String sendSmsCode(String phone, String code){
    String method = "GET";
    Map<String, String> headers = new HashMap<String, String>();
    //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
    headers.put("Authorization", "APPCODE " + this.appCode);
    Map<String, String> querys = new HashMap<String, String>();
    querys.put("code", code);
    querys.put("phone", phone);
    querys.put("skin", this.skin);
    querys.put("sign", this.sign);
    HttpResponse response = null;
    try {
      response = HttpUtils.doGet(this.host, this.path, method, headers, querys);
      //获取response的body
      if(response.getStatusLine().getStatusCode() == 200){
        return EntityUtils.toString(response.getEntity());
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "fail_" + response.getStatusLine().getStatusCode();
  }
}

二、验证码防刷校验

@Controller
@RequestMapping("/sms")
public class SmsSendController {
  @Autowired
  private SmsComponent smsComponent;
  /*** 提供给别的服务进行调用的
   */
  @GetMapping("/sendcode")
  public R sendCode(@RequestParam("phone") String phone, @RequestParam("code") String code){
    if(!"fail".equals(smsComponent.sendSmsCode(phone, code).split("_")[0])){
      return R.ok();
    }
    return R.error(BizCodeEnum.SMS_SEND_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_SEND_CODE_EXCEPTION.getMsg());
  }
}

🚩思路是将每一次发的验证码存在redis,并且加上存放的当前时间,下一次发验证码请求时先判断当前时间-上一次存放时间,如果小于60秒,返回错误,否则才发验证码请求

/** 接收到一个手机号,在此处生成验证码和缓存,然后转给第三方服务让他给手机发验证按
   * */
  @ResponseBody
  @GetMapping("/sms/sendcode")
  public R sendCode(@RequestParam("phone") String phone){
    //  TODO 接口防刷(冷却时长递增),redis缓存 sms:code:电话号
    String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
    // 如果不为空,返回错误信息
    if(null != redisCode && redisCode.length() > 0){
      long CuuTime = Long.parseLong(redisCode.split("_")[1]);
      if(System.currentTimeMillis() - CuuTime < 60 * 1000){ // 60s
        return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
      }
    }
    // 生成验证码
    String code = UUID.randomUUID().toString().substring(0, 6);
    String redis_code = code + "_" + System.currentTimeMillis();
    // 缓存验证码
    stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, redis_code , 10, TimeUnit.MINUTES);
    try {// 调用第三方短信服务
      return thirdPartFeignService.sendCode(phone, code);
    } catch (Exception e) {
      log.warn("远程调用不知名错误 [无需解决]");
    }
    return R.ok();
  }

三、注册环境

@PostMapping("/register")
  public String register(@Valid UserRegisterVo userRegisterVo,
               BindingResult result,
               RedirectAttributes redirectAttributes){
    if(result.hasErrors()){
      // 将错误属性与错误信息一一封装
      Map<String, String> errors = result.getFieldErrors().stream().collect(
          Collectors.toMap(FieldError::getField, fieldError -> fieldError.getDefaultMessage()));
      // addFlashAttribute 这个数据只取一次
      redirectAttributes.addFlashAttribute("errors", errors);
      return "redirect:http://auth.gulimall.com/reg.html";
    }
/**
   * TODO 重定向携带数据,利用session原理 将数据放在sessoin中 取一次之后删掉
   *
   * TODO 1. 分布式下的session问题
   * 校验
   * RedirectAttributes redirectAttributes : 模拟重定向带上数据
   */
  @PostMapping("/register")
  public String register(@Valid UserRegisterVo userRegisterVo,
               BindingResult result,
               RedirectAttributes redirectAttributes){
    if(result.hasErrors()){
      // 将错误属性与错误信息一一封装
      Map<String, String> errors = result.getFieldErrors().stream().collect(
          Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
      // addFlashAttribute 这个数据只取一次
      redirectAttributes.addFlashAttribute("errors", errors);
      return "redirect:http://auth.gulimall.com/reg.html";
    }
    // 开始注册 调用远程服务
    // 1.校验验证码
    String code = userRegisterVo.getCode();
    String redis_code = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + userRegisterVo.getPhone());
    if(!StringUtils.isEmpty(redis_code)){
      // 验证码通过
      if(code.equals(redis_code.split("_")[0])){
        // 删除验证码
        stringRedisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + userRegisterVo.getPhone());
        // 调用远程服务进行注册
        R r = memberFeignService.register(userRegisterVo);
        if(r.getCode() == 0){
          // 注册成功,去登录
          return "redirect:http://auth.gulimall.com/login.html";
        }else{
          Map<String, String> errors = new HashMap<>();
          errors.put("msg",r.getData("msg",new TypeReference<String>(){}));
          // 数据只需要取一次
          redirectAttributes.addFlashAttribute("errors",errors);
          return "redirect:http://auth.gulimall.com/reg.html";
        }
      }else{
        Map<String, String> errors = new HashMap<>();
        errors.put("code", "验证码错误");
        // addFlashAttribute 这个数据只取一次
        redirectAttributes.addFlashAttribute("errors", errors);
        return "redirect:http://auth.gulimall.com/reg.html";
      }
    }else{
      Map<String, String> errors = new HashMap<>();
      errors.put("code", "验证码错误");
      // addFlashAttribute 这个数据只取一次
      redirectAttributes.addFlashAttribute("errors", errors);
      return "redirect:http://auth.gulimall.com/reg.html";
    }
  }
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
JavaScript Java 应用服务中间件
谷粒商城:认证服务准备+60s短信验证
谷粒商城:认证服务准备+60s短信验证
|
5月前
|
数据采集 安全 容灾
《阿里云产品手册2022-2023 版》——号码认证服务
《阿里云产品手册2022-2023 版》——号码认证服务
105 0
|
移动开发 API 开发工具
秒懂云通信:如何使用阿里云号码认证服务(小白指南)
手把手教你如何使用阿里云号码认证服务,超详细控制台步骤解析,快速上手!
3029 0
秒懂云通信:如何使用阿里云号码认证服务(小白指南)
|
安全 数据安全/隐私保护 开发者
阿里云通信发布全新号码认证服务, 重新定义手机号码认证的方式
12月12日,阿里云通信宣布号码认证服务正式商用,将重新定义手机号码认证的方式。因移动应用实名制的政策要求,手机号码认证在移动APP的注册、登录等场景用的越来越多。而对于开发者来说,能完成手机号码认证的选择并不多,一般是借助短信、语音的基础通信通道,自己实现短信验证码或语音验证码来实现。
25063 0
|
SQL 前端开发 应用服务中间件
学成在线----day2
学成在线----day2
|
缓存 监控 算法
学成在线----day6
学成在线----day6
|
8月前
|
关系型数据库 MySQL 开发工具
谷粒商城--环境部署(2022/7/28最新)
谷粒商城--环境部署(2022/7/28最新)
187 0
谷粒商城--环境部署(2022/7/28最新)
|
存储 JSON 算法
学成在线----认证服务
学成在线----认证服务