跨域

113 阅读3分钟

一、什么是同源

源=协议+域名+端口号
如果两个url的协议、域名、端口号完全一致,那么这两个url就是同源
举例:
qq.com 、www.baidu.com 不同源
baidu.com 、www.baidu.com 不同源

  • 完全一致才算同源

同源策略怎么做?

只要在浏览器里打开页面,就默认遵守同源策略。

优点

保证用户的隐私安全和数据安全。

缺点

很多时候,前端需要访问另一个域名的后端接口,会被浏览器阻止其获取响应。
比如:甲站点通过 AJAX 访问乙站点的 /money 查询余额接口,请求会发出,但是响应会被浏览器屏蔽。

二、什么是跨域

跨域:跨域名的访问,以下情况都属于跨域:

  1. 域名不同 www.jd.com 与 www.taobao.com
  2. 域名相同,端口不同 www.jd.com:8080 与 www.jd.com:8081
  3. 二级域名不同 item.jd.com 与 miaosha.jd.com
  4. 如果域名和端口都相同,但是请求路径不同,不属于跨域,如:
    www.jd.com/item和www.jd…
  5. 跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。

三、JSONP 跨域

JSONP (JSON with Padding)是一个简单高效的跨域方式,html中的script标签可以加载并执行其他域的JavaScript,于是我们可以通过script标记来动态加载其他域的资源。
例如:
frank.com访问qq.com

  1. qq.com 将数据写到/frends.js
  2. frank.com 用script标签引用/frends.js
  3. /frends.js执行(执行frank.com事先定义好的window['{{xxx}}']( {{data}} )函数)
  4. 然后frank.com就能通过window.xxx获取到数据了

a. 甲站点利用 script 标签可以跨域的特性,向乙站点发送 get 请求。
b. 乙站点后端改造 JS 文件的内容,将数据传进回调函数。
c. 甲站点通过回调函数拿到乙站点的数据。

  • JSONP易于实现,但是也会存在一些安全隐患,如果第三方的脚本随意地执行,那么它就可以篡改页面内容,截获敏感数据。但是在受信任的双方传递数据,JSONP是非常合适的选择。

四、CORS 跨域

它的全称叫做Cross-Origin Resource Sharing,也就是跨域资源共享的意思,它是一种W3C规范,允许从浏览器的跨域通信。通过建立XMLHttpRequest对象的header,CORS允许开发者使用相同的习惯作为跨域请求工作。

  • CORS跨域分为简单请求和复杂请求
  1. 简单请求
    对于简单请求,浏览器直接发出CORS请求。具体来说,就是在乙站点响应头之中,增加Access-Control-Allow-Origin: http://甲站点
    例如:
    qq.com在响应头里写frank.com,可以使frank.com访问qq.com的数据

    response.setHeader("Access-Control-Allow-Origin", "http://frank.com")
    
  2. 复杂请求(非简单请求)

  • 非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json
  • 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
  • 浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
  • 响应 OPTIONS 请求,在响应中添加如下的响应头:
    Access-Control-Allow-Origin: https://甲站点
    Access-Control-Allow-Methods: POST, GET, OPTIONS, PATCH
    Access-Control-Allow-Headers: Content-Type
    
  • 响应 POST 请求,在响应中添加 Access-Control-Allow-Origin 头。
  1. 如果需要附带身份信息,JS 中需要在 AJAX 里设置 xhr.withCredentials = true