欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

跨域问题

程序员文章站 2022-07-10 12:12:10
...

浏览器同源策略

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

同源策略,它是由Netscape提出的一个著名的安全策略。
现在所有支持JavaScript 的浏览器都会使用这个策略。

所谓同源是指,域名,协议,端口相同。

如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。


产生跨域的原因

同时满足:

  • 浏览器限制
  • 跨域
  • XHR(XMLHttpRequest)请求

解决思路

跨域问题

 一、 浏览器      

        以Chrome浏览器为例

        找到chrome.exe所在目录,并在当前目录打开cmd

            跨域问题

        用cmd带参数启动一个Chrome:

        命令:  chrome --disable-web-security --user-data-dir=g:temp3

        跨域问题

        要带上--user-data-dir=g:temp3  否则不起作用

        新打开的浏览器提示下面信息时,说明已经成功,浏览器不会做同源校验

         跨域问题

      

 二、 XHR

   1.  使用JSONP

  • JSONP是什么

    JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

     由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。

     利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。

     用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。


  • 使用JSONP后台需要改动吗
  // 前端请求测试代码
$.ajax({

           url: '//localhost:8080/test/get',
            type: 'get',
            /*dataType: 'jsonp',*/
            success: function(data){
                console.log(JSON.stringify(data))
            }
  })

   未添加dataType: 'jsonp'

      浏览器报:No 'Access-Control-Allow-Origin' , 未报其他错误 

   添加上 dataType: 'jsonp'

      浏览器报jQuery错误

       原因:

       跨域问题

       是jQuery把返回结果:{"悟空":"是只猴子"} 当成方法来解析时出错,   故后端需要做相应调整

  • Spring boot 框架下支持JSONP  

       使用AbstractJsonpResponseBodyAdvice来支持跨域请求很简单,只需要继承这个类就可以了。具体代码如下:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
    public JsonpAdvice() {
        super("callback");
    }
}

   添加上已上代码后,再次请求接口,浏览器没有报错,取得正确结果:

/**/jQuery32107660470166019324_1524727420424({"悟空":"是只猴子"});

 请求url:

    http://localhost:8080/test/get?callback=jQuery32107660470166019324_1524727420424&_=1524727420425

    callback=jQuery32107660470166019324_1524727420424  

    callback参数是jQuery处理生成的                    


  JSONP请求成功的原因 ?  

   非jsonp请求:

     跨域问题

     jsonp请求:

     跨域问题

    jsonp发送的请求是script请求,区别于xhr请求,不存在跨域的问题。

    原理:jsonp请求中,对应后台中约定的callback,json代码的内容就是callback的值作为函数名,返回的的数据作为函数的参数。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

     xhr请求与JSONP请求区别:

      1. 请求type不同, json请求为xhr,jsonp为script

      2. 返回类型不同,jsonp返回的是javascript, 普通的xhr请求返回的是json数据对象

          跨域问题

      3. 请求URL的不同,请求带有callback字段

     JSONP请求参数

        callback:jQuery32107660470166019324_1524727420424

        _:1524727420425

        参数'_'的作用是: 防止该请求被缓存

        在ajax请求中加入 cache: true  ( 表示该请求可以被缓存 )时,再次请求,则参数中没有' _ ' 参数

     JSONP的弊端

         ●  服务端需要改动

         ●  只支持GET请求

         ●  发送的不是XHR请求    

              JSONP请求时 无法使用beforeSend,complete等回调函数

              ajax请求时指定dataType为jsonp类型,意味着将会通过script标签而不是XMLHttpRequest对象从从服务器接收数据。这种情况下,

              $.ajax()不再返回XMLHttpRequest对象,并且也不会传递事件处理函数,比如beforeSend。

 //////////////////////////////////////////////////////////////////////////////////////////////////////////////

2. 被调用方解决

 待补充

   ****带cookie的跨域****

        默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。

        通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
})

        如果服务器接收带凭据的请求,会用下面的HTTP头部来响应。Access-Control-Allow-Credentials: true

        在Java下的实现大概是这个样子:

response.addHeader("Access-Control-Allow-Credentials", "true");

        带cookie跨域的Access-Control-Allow-Origin头,再设置为*就不行了,会报错。

        在Access-Control-Allow-Credentials设置为true的时候,Access-Control-Allow-Origin不能被设置为通配符。所以解决思路就是在返回的时候设置为请求头中Origin的值。

        在Java下的实现大致是这样的:

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

        这样就能实现基于cors的携带cookies的跨域访问了。

        另外,支持withCredentials属性的浏览器有Firefox 3.5+、Safari 4+和Chrome。IE10及更早版本都不支持。

3. 调用方解决

 待补充

---------------------------------

跨域相关文章:

http://www.ruanyifeng.com/blog/2016/04/cors.html

http://mp.weixin.qq.com/s/A0Oi-fUrmboRPPeNEjG3aw