zoukankan      html  css  js  c++  java
  • HTTP(“跨域问题”和“防止表单重复提交”)

    一.跨域问题

      能够正常请求,但是没有办法获取到响应结果
    解决方案一:设置请求头,在请求的资源中设置Access-Control-Allow-Origin请求头
    //3.设置请求头
    response.setHeader("Access-Control-Allow-Origin", "*");

    解决方案二:.JSONP解决跨域问题
    普通的跨域访问问题,浏览器会进行拦截,凡是src属性的都不会拦截
    ajax:http://www.a.com:8080/a/AServlet

    JSONP实现原理:动态加载<script>标签,利用src属性进行服务器资源的访问,但是只支持Get请求
    1.在我们的Ajax请求当中,需要以JSONP方式请求(通过jquery手段,动态生成sript)

    jsonp:"代表的时前台传给后台,后台再传递给你 jsonpCallBack"

    2.再AJAX请求当中需要将返回的数据格式指定为jsonp

    dataType:"JSONP"

    3.JSONP需要以Get请求发送 ?username=zhangsan


    4.后台需要做的事情:
    1.正常接收数据

    2.返回数据

    前台传递过来的jsonp需要原路返回

    String jsonp=request.getP("jsonpCallBack");

    需要将返回的数据转换为JSON success

    response.getWirter.write(jsonp+"("+返回的数据+")");




    解决方案:
    修改Ajax请求:
    $("#button").click(function () {
    //获取到文本框的值
    var username=$("#username").val();
    //发送Ajax请求www.a.com的A工程
    $.ajax({
    url:"http://www.a.com:8080/a/AServlet?username="+username,
    type:"GET",
    jsonp:"jsonpCallBack", //回调函数
    dataType:"JSONP",
    success:function (result) {
    alert(result);
    },
    error:function () {
    alert('系统错误~')
    }
    });
    });

    更改后台请求,需要将JSONP原路返回
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.接受数据
    String username=request.getParameter("username");
    System.out.println("接受的数据:"+username);

    //接受Ajax传递的数据
    String jsonpCallBack = request.getParameter("jsonpCallBack");
    System.out.println("jsonpCallBack:"+jsonpCallBack);

    String success = JSON.toJSONString("success");
    //2.响应结果,数据必须为JSON格式
    response.getWriter().write(jsonpCallBack+"("+success+")");
    //3.设置请求头
    /*response.setHeader("Access-Control-Allow-Origin", "*");*/
    }
    三.使用HTTPClient解决:就是不通过浏览器发送请求
    B工程的页面发送的Ajax没有办法请求到A工程,因为浏览器会拦截,走后台,后台通过HTTPClient请求请求到A工程,获取到响应结果


    1.B工程的Bindex.jsp页面请求到B工程的Servlet
    $("#button").click(function () {
    //获取到文本框的值
    var username=$("#username").val();
    //发送Ajax请求www.a.com的A工程
    $.ajax({
    url:"BServlet?username="+username,
    type:"GET",
    success:function (result) {
    alert(result);
    },
    error:function () {
    alert('系统错误~')
    }
    });
    });
    2.B工程的BServlet去模拟HTTP请求到A工程
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //内部通过HTTPClient进行转发
    //构建一个连接
    CloseableHttpClient client = HttpClients.createDefault();
    //构建请求
    HttpGet get=new HttpGet("http://www.a.com:8080/a/AServlet?username="+request.getParameter("username"));
    //发送请求
    CloseableHttpResponse httpResponse = client.execute(get);
    //获取返回结果
    String result = EntityUtils.toString(httpResponse.getEntity());
    //将A工程响应结果给页面
    response.getWriter().write(result);

    }
    3.A工程处理请求
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.接受数据
    String username=request.getParameter("username");
    System.out.println("接受的数据:"+username);

    //2.响应结果
    response.getWriter().write("success");

    }

    二.防止表单重复提交
    1.网络延迟,再网络延迟时间内,频繁的提交表单
    只能提交一次,监控表单的提交事件,通过一个boolean类型的变量来区分已经点击过还是没有点击,如果已经点击过,表单就不提交,没有点击过再提交



    2.重新加载或者后退页面
    思路如下:在我访问登录页面的时候,创建一个 Token令牌(当作一个标识) ,保存到session当中,然后再表单提交的时候将令牌一起提交
    后台Servlet去判断session当中的令牌和表单提交的令牌是否相等,如果相等代表正常提交(session清空),如果不相等,代表非正常提交


    Form.jsp页面
    <body>
    <form action="FormServlet" onsubmit="return formSubmit()" method="post">
    <input type="hidden" id="hiddenToken" name="formToken"/>
    <input type="text" name="username"/>
    <input type="submit" value="提交"/>
    </form>
    </body>


    <script type="text/javascript">
    //创建一个变量 false代表没有点击过,true代表已经点击过
    var flag=false;
    function formSubmit() {
    if(!flag){ //取反值为false
    flag=true;
    return true;
    }else {
    return false;
    }
    }

    $(function () {
    //生成令牌
    $.ajax({
    url:"TokenServlet",
    type:"POST",
    success:function (token) {
    $("#hiddenToken").val(token);
    }
    })
    })
    </script>

    TokenServlet:
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //生成令牌
    String token = UUID.randomUUID().toString();
    //令牌保存到session当中
    request.getSession().setAttribute("sessionToken",token);
    //响应
    response.getWriter().write(token);
    }

    FormServlet:
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //验证令牌
    //获取页面提交的隐藏域数据
    String formToken = request.getParameter("formToken");
    //获取Session中的Token
    String sessionToken = (String)request.getSession().getAttribute("sessionToken");
    //如果页面中获取的和session中不一致,代表已经提交过了,不要重复提交
    if(!formToken.equals(sessionToken)){
    response.getWriter().write("不要重复提交~");
    return;
    }

    //接收数据
    String username = request.getParameter("username");
    System.out.println("接收的数据为:"+username);
    //必须将token清空,不然永远是一致的
    request.getSession().removeAttribute("sessionToken");

    try {
    //模拟网络延迟
    Thread.sleep(300);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    //返回数据
    response.getWriter().write("success");
    }

  • 相关阅读:
    UDP:用户数据报协议(User Datagram Protocol)
    线程池的使用
    SQL Server表和模式空间使用情况http://www.51myit.com/thread2466911.html
    bytetobmp and bmptobyte(Image)
    c# TCP例子转载
    POJ 4047Garden
    NYOJ 102 次方求模
    Sum
    POJ 1094 Sorting It All Out(经典拓扑,唯一排序)
    POJ 2387 Til the Cows Come Home(Dijkstra)
  • 原文地址:https://www.cnblogs.com/rzbwyj/p/12268989.html
Copyright © 2011-2022 走看看