【認證服務】驗證碼、社交登入、分散式session、單點登入
阿新 • • 發佈:2021-11-03
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; @Configurationpublic 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"; 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; /*** 提供給別的服務進行呼叫的 該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";