【認證服務】驗證碼、社交登錄、分佈式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";
        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";

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章