同源策略及跨域

  • Post author:
  • Post category:其他




同源策略和跨域



1.同源策略

如果两个页面的协议,域名和端口都相同,则两个页面具有

相同的源

例如,下表给出了相对于 http://www.test.com/index.html 页面的同源检测:


URL

是否同源

原因
http://www.test.com/other.html 同源(协议、域名、端口相同)
https://www.test.com/about.html 协议不同(http 与 https)
http://blog.test.com/movie.html 域名不同(www.test.com 与 blog.test.com)
http://www.test.com:7001/home.html 端口不同(默认的 80 端口与 7001 端口)
http://www.test.com:80/main.html 同源(协议、域名、端口相同)


同源策略

(英文全称 Same origin policy)是浏览器提供的一个安全功能。

通俗的理解:浏览器规定,A 网站的 JavaScript,不允许和非同源的网站 C 之间,进行资源的交互,例如:

  • 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
  • 无法接触非同源网页的 DOM
  • 无法向非同源地址发送 Ajax 请求



2.跨域


同源

指的是两个 URL 的协议、域名、端口一致,反之,则是

跨域

出现跨域的根本原因:

浏览器的同源策略

不允许非同源的 URL 之间进行资源的交互。

注意:浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!

现如今,实现跨域数据请求,最主要的两种解决方案,分别是

JSONP



CORS


JSONP

:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。


CORS

:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。



JSONP

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

由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。但是

<script>

标签不受浏览器同源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。

因此,JSONP 的实现原理,就是通过

<script>

标签的 src 属性,请求跨域的数据接口,并通过

函数调用

的形式,接收跨域接口响应回来的数据。



1.简单的JSONP

 <script>
   function success(data) {
     console.log('获取到了data数据:')
     console.log(data)
   }
 </script>
<script src="http://ajax.frontend.itheima.net:3006/api/jsonp?callback=success&name=zs&age=20"></script>



2.jQuery中的JSONP

 $.ajax({
    url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
    // 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
    dataType: 'jsonp',
    success: function(res) {
       console.log(res)
    }
 })

默认情况下,使用 jQuery 发起 JSONP 请求,会自动携带一个 callback=jQueryxxx 的参数,jQueryxxx 是随机生成的一个回调函数名称。

 $.ajax({
    url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
    dataType: 'jsonp',
    // 发送到服务端的参数名称,默认值为 callback
    jsonp: 'callback',
    // 自定义的回调函数名称,默认值为 jQueryxxx 格式
    jsonpCallback: 'abc',
    success: function(res) {
       console.log(res)
    }
 })

jQuery 中的 JSONP,也是通过

<script>

标签的 src 属性实现跨域数据访问的,只不过,jQuery 采用的是动态创建和移除

<script>

标签的方式,来发起 JSONP 数据请求。

在发起 JSONP 请求的时候,动态向

<header>

中 append 一个

<script>

标签;

在 JSONP 请求成功以后,动态从

<header>

中移除刚才 append 进去的

<script>

标签;



3.JSONP的优缺点

优点:

  • 它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略;
  • 它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
  • 在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方。这个就相当于将controller层和view层终于分开了。我提供的jsonp服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续view操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个jsonp服务。

缺点

  • 它只支持GET请求而不支持POST等其它类型的HTTP请求
  • 它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
  • jsonp在调用失败的时候不会返回各种HTTP状态码。
  • 安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。



CORS

CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列 HTTP 响应头组成,

这些


HTTP


响应头决定浏览器是否阻止前端


JS


代码跨域获取资源

浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制。

  • CORS 主要在服务器端进行配置。客户端浏览器

    无须做任何额外的配置

    ,即可请求开启了 CORS 的接口。
  • CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。



1.CORS 响应头部

  • Access-Control-Allow-Origin

    • origin 参数的值指定了允许访问该资源的外域 URL

    • res.setHeader('Access-Control-Allow-Origin','http://itcast.cn')
      res.setHeader('Access-Control-Allow-Origin','*')
      
  • Access-Control-Allow-Headers

    • 如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 Access-Control-Allow-Headers 对额外的请求头进行声明,否则这次请求会失败!

    • 默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头:

      Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)

    • res.setHeader('Access-Control-Allow-Headers','Content-Type ')
      
  • Access-Control-Allow-Methods

    • 默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。

    • 如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过 Access-Control-Alow-Methods来指明实际请求所允许使用的 HTTP 方法。

    • res.setHeader('Access-Control-Allow-Methods','*')
      



2.CORS请求的分类


简单请求

  • 请求方式:GET、POST、HEAD 三者之一
  • HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)


预检请求

  • 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
  • 请求头中包含自定义头部字段
  • 向服务器发送了 application/json 格式的数据

在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。


简单请求的特点

:客户端与服务器之间只会发生一次请求。


预检请求的特点

:客户端与服务器之间会发生两次请求,OPTION 预检请求成功之后,才会发起真正的请求。



版权声明:本文为weixin_42692293原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。