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

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

@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";
		}
	}

你可能感兴趣的:(项目,spring,boot,后端)