Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

我在学习Java秒杀系统视频,遇到了关于ajax请求异步的问题(第一次用到ajax,不知道是不是这么称呼)。

其中有一个功能是输入手机号后获取验证码。下面是获取验证码页面getotp.html

<!--省略头文件等-->

<body class="login">
    <div class="content">
        <h3 class="form-title">获取otp信息</h3>
        <div class="form-group">
            <label class="control-label">手机号</label>
            <div>
                <input  class="form-control" type="text" placeholder="手机号" name="telphone" id="telphone"/>
            </div>    
        </div>    
        <div class="form-actions">
            <button class="btn blue" id="getotp" type="submit">
                获取otp短信
            </button>    
        </div>    
    </div>    


</body>
<script>

    jQuery(document).ready(function(){

        //绑定otp的click时间用于向后端发送获取手机验证码的请求
        $("#getotp").on("click",function(){
            var telphone = $("#telphone").val();
            if(telphone == null || telphone == ""){
                alert("手机号不能为空");
                return false;
            }
            $.ajax({
                type:"POST",
                contentType:"application/x-www-form-urlencoded",
                url:"http://localhost:8090/user/getotp",
                data:{
                    "telphone":$("#telphone").val(),
                },
                xhrFields:{withCredentials:true},
                success:function(data){
                    if(data.status == "success"){
                        alert("otp已经发送到了您的手机上,请注意查收");
                        window.location.href="./register.html";
                    }else{
                        alert("otp发送失败,原因为"+data.data.errMsg);
                    }
                },
                error:function(data){
                    alert("otp发送失败,原因为"+data.responseText);
                }
            });
            return false;
        });


    });

</script>

在输入完手机号后,跳转至userController的getOtp方法。该方法在算出验证码后,将电话-验证码放入HttpServletRequest的getSession里,然后在控制台输出电话号码和验证码,最后返回状态码success,跳转至注册页面register.html,如下所示:

<body class="login">
    <div class="content">
        <h3 class="form-title">用户注册</h3>
        <div class="form-group">
            <label class="control-label">手机号</label>
            <div>
                <input  class="form-control" type="text" placeholder="手机号" name="telphone" id="telphone"/>
            </div>    
        </div>
        <div class="form-group">
            <label class="control-label">验证码</label>
            <div>
                <input  class="form-control" type="text" placeholder="验证码" name="otpCode" id="otpCode"/>
            </div>    
        </div>    
        <div class="form-group">
            <label class="control-label">用户昵称</label>
            <div>
                <input  class="form-control" type="text" placeholder="用户昵称" name="name" id="name"/>
            </div>    
        </div>    
        <div class="form-group">
            <label class="control-label">性别</label>
            <div>
                <input  class="form-control" type="text" placeholder="性别" name="gender" id="gender"/>
            </div>    
        </div>
        <div class="form-group">
            <label class="control-label">年龄</label>
            <div>
                <input  class="form-control" type="text" placeholder="年龄" name="age" id="age"/>
            </div>    
        </div>
        <div class="form-group">
        <label class="control-label">密码</label>
            <div>
                <input  class="form-control" type="password" placeholder="密码" name="password" id="password"/>
            </div>    
        </div>            
        <div class="form-actions">
            <button class="btn blue" id="register" type="submit">
                提交注册
            </button>    
        </div>    
    </div>    


</body>


<script>

    jQuery(document).ready(function(){

        //绑定otp的click时间用于向后端发送获取手机验证码的请求
        $("#register").on("click",function(){
            var telphone = $("#telphone").val();
            var password = $("#password").val();
            var age = $("#age").val();
            var gender = $("#gender").val();
            var name = $("#name").val();
            var otpCode = $("#otpCode").val();
            if(telphone == null || telphone == ""){
                alert("手机号不能为空");
                return false;
            }
            if(password == null || password == ""){
                alert("密码不能为空");
                return false;
            }
            if(age == null || age == ""){
                alert("年龄不能为空");
                return false;
            }
            if(gender == null || gender == ""){
                alert("性别不能为空");
                return false;
            }
            if(otpCode == null || otpCode == ""){
                alert("密码不能为空");
                return false;
            }

            $.ajax({
                type:"POST",
                contentType:"application/x-www-form-urlencoded",
                url:"http://localhost:8090/user/register",
                data:{
                    "telphone":$("#telphone").val(),
                    "password":password,
                    "age":age,
                    "gender":gender,
                    "otpCode":otpCode,
                    "name":name
                },
                xhrFields:{withCredentials:true},
                success:function(data){
                    if(data.status == "success"){
                        alert("注册成功");
                        window.location.href="./login.html";
                    }else{
                        alert("注册失败,原因为"+data.data.errMsg);
                    }
                },
                error:function(data){
                    alert("注册失败,原因为"+data.responseText);
                }
            });
            return false;
        });


    });


</script>

填写完后点击按钮后,发起ajax请求到UserController的register方法,该方法会先从HttpServletRequest.getSession()中取出先前在getotp方法里放入的电话-验证码键值对。

我的问题出现在这里:我可以肯定在getotp方法里是成功将电话-验证码放入session里,但在register方法中getSession()里取出电话对应的验证码是空的。

@Controller("user")
@RequestMapping("/user")
@CrossOrigin(allowCredentials="true", allowedHeaders = "*")
public class UserController  extends BaseController{

    @Autowired
    private UserService userService;

    @Autowired
    private HttpServletRequest httpServletRequest;


    //用户注册接口
    @RequestMapping(value = "/register",method = {RequestMethod.POST},consumes={CONTENT_TYPE_FORMED})
    @ResponseBody
    public CommonReturnType register(@RequestParam(name="telphone")String telphone,
                                     @RequestParam(name="otpCode")String otpCode,
                                     @RequestParam(name="name")String name,
                                     @RequestParam(name="gender")Integer gender,
                                     @RequestParam(name="age")Integer age,
                                     @RequestParam(name="password")String password) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
        
        //验证手机号和对应的otpcode相符合
        String inSessionOtpCode = (String) this.httpServletRequest.getSession().getAttribute(telphone);
        if(!com.alibaba.druid.util.StringUtils.equals(otpCode,inSessionOtpCode)){
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"短信验证码不符合");
        }
      //...此处省略
    }

    public String EncodeByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //确定计算方法
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        BASE64Encoder base64en = new BASE64Encoder();
        //加密字符串
        String newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
        return newstr;
    }


    //用户获取otp短信接口
    @RequestMapping(value = "/getotp",method = {RequestMethod.POST},consumes={CONTENT_TYPE_FORMED})
    @ResponseBody
    public CommonReturnType getOtp(@RequestParam(name="telphone")String telphone){
        //需要按照一定的规则生成OTP验证码
        Random random = new Random();
        int randomInt =  random.nextInt(99999);
        randomInt += 10000;
        String otpCode = String.valueOf(randomInt);


        //将OTP验证码同对应用户的手机号关联,使用httpsession的方式绑定他的手机号与OTPCODE
        httpServletRequest.getSession().setAttribute(telphone,otpCode);

        //将OTP验证码通过短信通道发送给用户,省略
        System.out.println("telphone = " + telphone + " & otpCode = "+otpCode);


        return CommonReturnType.create(null);
    }

在视频里老师说这是异步请求的问题导致session里取不到值,可以通过在controller里添加

@CrossOrigin(allowCredentials="true", allowedHeaders = "*")

注解以及在页面里的ajax请求里添加

xhrFields:{withCredentials:true}

就可以解决,但我在这里运行老师给的代码并没解决此问题。

此外如果页面所在的文件夹是放在项目文件夹里,则不会出现session取不到验证码的问题,但如果页面所在文件夹是独立放在项目文件夹以外的地方,就会出现这个问题。

请教一下我该怎么做?

Springboot版本为2.0.5

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
311 views
Welcome To Ask or Share your Answers For Others

1 Answer

@CrossOrigin是处理跨域的,不知道项目结构是啥,目测和跨域没啥关系,只能提供一些思路:

  1. session 需要 session-id,默认情况下 session-id 是在 cookie 里的
  2. 所以要查看第一个请求有没有设置 session-id 到 cookie 里
  3. 然后查看第二个请求有没有带着 session-id 去请求
  4. 我注意到代码里取值用的telephone参数,这不闹么,建议使用固定key

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...