说明: 本篇博客目的在于学习如何通过短信发送验证码的问题。。。

Controller层,获取otp短信接口

//用户获取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);
}

说明:其中第三步的短信通道可以购买第三方服务,将验证码模板发送到用户手机上!!!

测试:

Spring注入的request会不会存在线程安全?后一个request覆盖前一个request?

Spring能实现在多线程环境下,将各个线程的request进行隔离,且准确无误的进行注入,奥秘就是ThreadLocal

HttpServletRequest利用 autowire 注入,线程安全问题_weixin_33940102的博客-CSDN博客

美化Otp页面

css - Bootstrap 之 Metronic 模板的学习之路 - (1)总览_个人文章 - SegmentFault 思否

getotp.html页面代码:

<html>
<head>
<meta charset="UTF-8">
<link href="static/assets/global/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="static/assets/global/css/components.css" rel="stylesheet" type="text/css"/>
<link href="static/assets/admin/pages/css/login.css" rel="stylesheet" type="text/css"/>
<script src="static/assets/global/plugins/jquery-1.11.0.min.js" type="text/javascript"></script>
<script src="./gethost.js" type="text/javascript"></script>
 
</head>
 
<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>
 
 
</html>

window.location.href 之后,重新创建了一个新的httpcontext  ,所以导致session丢失了

解决:inSessionOtpCode=null的问题,虽然下面代码可行,但是根本问题没解决,换了火…-MK网

这里还是有问题,这里验证码从URI中取,并没有从session中取,所有暂时无法解决问题,这里待解决。。。

说明:

然后在下面添加一些对应的标签名即可!

Ajax学习: Ajax简介

注意:

Ajax跨域请求问题,设置一下属性就可以了,     前端 Ajax 请求中添加 xhrFields: {withCredentials: true},     后端 controller 层添加 @CrossOrigin(origins = ”*”, allowCredentials = “true”) 就可以访问了

一篇轻松解决跨域问题 - 知乎

xhrFields:{ withCredentials: true }使用post请求,该参数作用详解_宋哈哈的博客-CSDN博客_xhrfields

怎么感觉跨域有点像分布式里的Feign远程调用问题啊?待解决。。。

拓展-跨域问题

什么是跨域

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

如下给出了跨域的几种情况

为什么会有跨域问题

核心原因在于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。

这里有一个关键词浏览器大家一定要记住,受跨域影响的只在浏览器范围。无论是前端和后端一定要记住限制的宿主。因为之前的工作中曾经不止一次的有经验不足的小伙伴问到,为什么接口给app用没问题,pc或者H5一调就不行,肯定是他们调用的问题。这里再提醒一下,native调用接口的时候是没有经过浏览器的。只有通过**浏览器发起的ajax请求,**在跨域的时候会受到同源限制。app navtive直接调用,或者server端发起的http请求等等均不会受到影响。

受到同源限制的范围

浏览器同源限制的地方主要有如下三处,因为本篇的标题已经明确是接口跨域相关所有后续的方案也只介绍ajax请求相关

  • Cookie、LocalStorage 和 IndexedDB
  • DOM
  • AJAX 请求

相关解决方案

  • 域名归一 解决跨域问题的第一个方案,将跨域的改成不跨域,域名相同了也就不存在跨域了。将前端项目和接口请求,通过反向代理工具如nginx将前端web项目和服务server的域名映射成同一域名即可。该方案适用于没有强制要求新开多个域名的公司内部项目,修改只需要向运维描述需求修改反向代理接口,当然如果没有运维自己调整也很快。
  • JSONP 浏览器中一个域名加载其他域名的script是不受限制的,jsonp的原理是调用的时候动态新增一个script标签扩展到dom上,然后请求脚本资源的形式向服务端发起http请求。server接收到请求后,以约定好的形式用回调函数名包裹数据的方式返回,如jsonpCallbackName({data:data})。script加载完毕后,就会立即执行该回调函数。此时就可以获得该数据。该方案适用于提供给第三方作为http的api,也可用于公司内部。缺点是如果要同时提供给app使用的话,需要接口调整适配app,或者app调整解析方式适配接口。
  • 跨域资源共享 CORS 该方案主要是服务端调整响应头,设置 Access-Control-Allow-Origin。具体设置要看服务端的架构情况。核心就是找到请求的响应出口,设置其response header值。如架构存在反向代理可以在nginx处对应转发处,设置header值。也可以在应用服务器设置header,不论是java的spring系列的跨域注解,go或者nodejs获者其他的web服务器,均记得找到对应设置response header的地方即可。适用公司内部项目,目前比较常用
  • 请求代理 举一个场景,如果你希望直接调用其他第三方的接口,如微博等等其他的第三方的不对外的ajax接口。此时直接在web下面肯定是无法直接通过,可以通过自己的服务器server端发起http请求,然后自己的web去调用自己服务端。适用场景个人项目
  • 其他 还有通过window.name + iframe跨域或者postMessage的方式因其目前不怎么常用,故这里不详细解释,有兴趣的同学可以百度深入了解。
  • 本地调试方案 前后端分离的项目里面,前端调试时跨域还可以通过浏览器(chrome)安装跨域插件,或者在前端项目里面启动代理方便开发核心应该也是基于cors,但是都只能本地调试使用。最终线上环境还是需要依赖以上前面给到的方案解决。