zoukankan      html  css  js  c++  java
  • 【认证服务】验证码、社交登录、分布式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";
  • 相关阅读:
    近两年目标
    Spring使用ajax异步上传文件
    java注解
    js 点击文本框,预览选择图片
    修改服务器系统时间(包括hive)
    队列原理
    EMR目录
    2个CDH的hive数据同步
    CDH建表字符集问题
    EMR的fair-scheduler.xml
  • 原文地址:https://www.cnblogs.com/wuwuyong/p/15501458.html
Copyright © 2011-2022 走看看