zoukankan      html  css  js  c++  java
  • 解决跨域问题

    跨域:就是浏览器的安全机制,要求该工程请求的域名需要一致,如果说请求域名不一致的情况下,浏览器没有办法直接返回结果;

    解决问题的方案:

      JSONP方式;

      Nginx方式;

      HttpClient方式;

      添加HTTP请求头方式;

    方案一:添加HTTP请求头

      后台response添加header,response.setHeader("Access-Control-Allow-Origin", "*"); 支持所有网站  

      项目搭建结构如下:创建两个独立的项目 

         

       后端代码:

    package com.wn;
    
    import com.alibaba.fastjson.JSON;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/aServlet")
    public class AServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    
        //方法一:使用请求头解决跨域问题
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            System.out.println("数据:"+username);
    
            //响应
            resp.getWriter().write("success");
    
            //添加请求头方式解决跨域
            resp.setHeader("Access-Control-Allow-Origin","*");
    
        }
    }

      前端代码:

    <%--
      Created by IntelliJ IDEA.
      User: wn
      Date: 2020/2/6
      Time: 10:04
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>跨域</title>
        <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
        <script>
            //使用请求头解决跨域问题
            $(function () {
                $("#button").click(function () {
                    var username=$("#username").val();
                   $.ajax({
                       url:"http://www.aproject.com:8080/aServlet",
                       data:{"username":username},
                       type:"POST",
                       success:function (result) {
                           alert(result)
                       },
                       error:function () {
                           alert("error!!!")
                       }
                   })
                })
            })</script>
    </head>
    <body>
      <input type="text" name="username" id="username"/><button id="button" type="button">提交</button>
    </body>
    </html>

    方案二:JSONP

      前端代码:

    <%--
      Created by IntelliJ IDEA.
      User: wn
      Date: 2020/2/6
      Time: 10:04
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>跨域</title>
        <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
        <script>
           //使用JSONP方式解决跨域问题
            $(function () {
                $("#button").click(function () {
                    var username=$("#username").val();
                    $.ajax({
                        url:"http://www.aproject.com:8080/aServlet?username="+username,
                        type:"GET",
                        jsonp:"jsonp",  //回调函数
                        dataType:"JSONP",
                        success:function (result) {
                            alert(result)
                        },
                        error:function () {
                            alert("error!!!")
                        }
                    })
                })
            })</script>
    </head>
    <body>
      <input type="text" name="username" id="username"/><button id="button" type="button">提交</button>
    </body>
    </html>

      后端代码:

    package com.wn;
    
    import com.alibaba.fastjson.JSON;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/aServlet")
    public class AServlet extends HttpServlet {
        //resp.setContentType("text/html;charset=utf-8");
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    //方法二:使用JSONP解决跨域问题 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); System.out.println("数据:"+username); //使用JSONP解决跨域问题 String jsonp = req.getParameter("jsonp"); //需要将返回的数据转换为JSON格式 String success = JSON.toJSONString("success"); resp.getWriter().write(jsonp+"("+success+")"); } }

      jquery中jsonp的实现原理

          在同源策略下,在某个服务器下的页面时无法获取到该服务器以外的数据的,即一般的ajax是不能进行跨域请求的。但是img,iframe,script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用script标签的开放策略,我们可以实现跨域请求数据,当然这需要服务器端的配合。jquery中ajax的核心是通过XmlHttpRequest获取非本业内容,而jsonp的核心则是动态添加,script标签来调用服务器提供的js脚本。

          当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据,而我们使用JSONP模式来请求数据的时候服务器返回的是一段可执行的JavaScript代码。因为JSONP跨域的原理就是用的动态加载,所以我们只能把参数通过URL的方式传递,所以JSONP的type类型只能是GET请求方式!

          使用JSONP模式来请求数据的整个流程:客户端发送一个请求,规定一个可执行的函数名(这里就是jquery做了封装的处理,自动帮我们生成回调函数并把数据取出来供success属性方法来调用,而不是传递一个回调句柄),服务器端接受定义的函数名称,然后把数据通过实参的形式发送出去。

          (在query源码中,JSONP的实现方式是动态添加script标签来调用服务器提供的JS脚本。jquery会在Window对象中加载一个全局的函数,当script代码插入时函数执行,执行完毕后就script标签会被移除。同时jquery还对非跨域的请求进行了优化,如果这个是在同一个域名下那么它就会像正常地ajax请求一样工作。)

      JSONP的优缺点

          JSONP的优点:它不像是XMLHttpRequest对象实现的ajax请求那样受到同源策略的限制,它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持,并且在请求完毕后可以通过调用callback的方式回传结果;

          JSONP的缺点:它只支持GET请求而不支持POST等其他类型的HTTP请求,它只支持跨域HTTP请求这种情况下,不能解决不同域的两个页面之间如何进行JavaScript调用的问题;

    方案三:HttpClient

      前端代码:

    <%--
      Created by IntelliJ IDEA.
      User: wn
      Date: 2020/2/6
      Time: 10:04
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>跨域</title>
        <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
        <script>
            //使用HttpClient方式解决跨域问题
            $(function () {
                $("#button").click(function () {
                    var username=$("#username").val();
                    $.ajax({
                        url:"httpServlet?username="+username,
                        type:"GET",
                        success:function (result) {
                            alert(result)
                        },
                        error:function () {
                            alert("error!!!")
                        }
                    })
                })
            })
    
        </script>
    </head>
    <body>
      <input type="text" name="username" id="username"/><button id="button" type="button">提交</button>
    </body>
    </html>

      HttpClient类:

    package com.wn;
    
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import sun.net.www.http.HttpClient;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/httpServlet")
    public class HttpCient extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //创建连接
            CloseableHttpClient client = HttpClients.createDefault();
            //请求
            HttpGet httpGet=new HttpGet("http://www.aproject.com:8080/aServlet?username="+req.getParameter("username"));
            //发送请求
            CloseableHttpResponse response = client.execute(httpGet);
            //获取返回结果  将A工程中的success提示语句返回给httpClient
            String s = EntityUtils.toString(response.getEntity());
            //响应   HttpClient将返回的结果响应给页面
            resp.getWriter().write(s);
        }
    }

      后端代码:

    package com.wn;
    
    import com.alibaba.fastjson.JSON;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/aServlet")
    public class AServlet extends HttpServlet {
        //resp.setContentType("text/html;charset=utf-8");
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    
        //方法三:使用HttpClient解决跨域问题
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            System.out.println("数据:"+username);
    
            //响应
            resp.getWriter().write("success");
        }
    }

      实现原理

          实现原理很简单,若想在B项目中通过ajax访问A项目获取结果,固然有ajax跨域问题,但是B项目中访问B项目获取结果,不存在跨域问题,这种方式实际上是在B项目中ajax请求范文B项目中的HttpClient,在通过HttpClient转发请求获取A项目中的数据结果。但这种方式产生了两次请求,效率低,但内部请求,比较安全。

    方案四:Nginx

      B项目不能直接请求A项目内容,可以通过Nginx,根据同域名,但项目名不同进行区分

      当我们访问www.bproject.com通过www.nginx.com/B访问,并通过nginx转达到www.bproject.com

      当我们访问www.aproject.com通过www.nginx.com/A访问,并通过nginx转达到www.aproject.com

    server {
            listen       80;
            server_name  www.nginx.com;
            location /A {
                proxy_pass  http://www.aproject.com:8080;
                index  index.html index.htm;
            }
            location /B {
                proxy_pass  http://www.bproject.com:8081;
                index  index.html index.htm;
            }
    }
  • 相关阅读:
    图解zookeeper FastLeader选举算法【转】
    win10 tensorflow python3*,Multiprocessing using fit_generator(pickle_safe=True) fail问题解决
    xcode从8升级到9出现的问题
    c++保存数据到TXT
    基于机器学习人脸识别face recognition具体的算法和原理
    pycharm 操作的一些设置,记录下
    ML-DL-各种资源汇总
    MATLAB实现多元线性回归预测
    【机器学习】 Matlab 2015a 自带机器学习算法汇总
    C++中嵌入python程序——命令行模式
  • 原文地址:https://www.cnblogs.com/wnwn/p/12268564.html
Copyright © 2011-2022 走看看