【认证服务】验证码、社交登录、分布式session、单点登录
https://blog.csdn.net/hancoder/article/details/114242184
一.验证码
package com.xunqi.gulimall.auth.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class GulimallWebConfig implements WebMvcConfigurer { /**· * 视图映射:发送一个请求,直接跳转到一个页面 * @param registry */ @Override public void addViewControllers(ViewControllerRegistry registry) { // registry.addViewController("/login.html").setViewName("login"); registry.addViewController("/reg.html").setViewName("reg"); } }
(1) 验证码倒计时js
$(function () { $("#sendCode").click(function () { if ($(this).hasClass("disabled")) { // 1.进入倒计时效果 } else { $.get("/sms/sendcode?phone=" + $("#phoneNum").val(), function (data) { if (data.code != 0) { layer.msg(data.msg) } }); // 2.给指定手机号发送验证码 timeoutChangeStyle() } }) }) // 外部变量计时 let num = 60; function timeoutChangeStyle() { $("#sendCode").attr("class", "disabled") if (num == 0) {//可以再次发送 num = 60; $("#sendCode").attr("class", "");//取消disabled $("#sendCode").text("发送验证码"); } else { var str = num + "s 后再次发送"; $("#sendCode").text(str); // 1s后回调 setTimeout("timeoutChangeStyle()", 1000); } num-- }
(2) 阿里云-短信服务
@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"; Mapheaders = new HashMap (); //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 headers.put("Authorization", "APPCODE " + this.appCode); Map querys = new HashMap (); 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; /*** 提供给别的服务进行调用的 该controller是发给短信服务的,不是验证的 */ @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()); } }
发送验证码:
@ResponseBody @GetMapping(value = "/sms/sendCode") public R sendCode(@RequestParam("phone") String phone) { //1、接口防刷 String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone); if (!StringUtils.isEmpty(redisCode)) { //活动存入redis的时间,用当前时间减去存入redis的时间,判断用户手机号是否在60s内发送验证码 long currentTime = Long.parseLong(redisCode.split("_")[1]); if (System.currentTimeMillis() - currentTime < 60000) { //60s内不能再发 return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(),BizCodeEnum.SMS_CODE_EXCEPTION.getMessage()); } } //2、验证码的再次效验 redis.存key-phone,value-code int code = (int) ((Math.random() * 9 + 1) * 100000); String codeNum = String.valueOf(code); String redisStorage = codeNum + "_" + System.currentTimeMillis(); //存入redis,防止同一个手机号在60秒内再次发送验证码 stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX+phone, redisStorage,10, TimeUnit.MINUTES); thirdPartFeignService.sendCode(phone, codeNum); return R.ok(); }
4) 后端JSR303校验校验
前端也可以进行校验,此处是后端的验证
@Data public class UserRegisterVo {// JSR303校验 @Length(min = 6,max = 20,message = "用户名长度必须在6-20之间") @NotEmpty(message = "用户名必须提交") private String userName; @Length(min = 6,max = 20,message = "用户名长度必须在6-20之间") @NotEmpty(message = "密码必须提交") private String password; @NotEmpty(message = "手机号不能为空") @Pattern(regexp = "^[1]([3-9])[0-9]{9}$", message = "手机号格式不正确") private String phone; @NotEmpty(message = "验证码必须填写") private String code; }
前面的JSR303校验怎么用:
JSR303校验的结果,被封装到BindingResult
,再结合BindingResult.getFieldErrors()
方法获取错误信息,有错误就重定向至注册页面
@PostMapping("/register") public String register(@Valid UserRegisterVo registerVo, BindingResult result, RedirectAttributes attributes) { if (result.hasErrors()){ return "redirect:http://auth.gulimall.com/reg.html";