跨域

481 阅读3分钟

什么是跨域

我们通常所说的跨域,是指由浏览器同源策略限制的一类请求场景。是指浏览器不能执行其他网站的脚本。是浏览器对JavaScript实施的安全限制。

什么是同源策略

所谓同源是指"协议+域名+端口"三者相同;即便是两个不同的域名指向同一个ip地址,也非同源

特别注意两点:
  1. 如果是协议和端口造成的跨域问题“前台”是无能为力的。
  2. 在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

常见跨域场景

URL                                      说明                    是否允许通信
http://www.domain.com/a.js
http://www.domain.com/b.js         同一域名,不同文件或路径           允许
http://www.domain.com/lab/c.js

http://www.domain.com:8000/a.js
http://www.domain.com/b.js         同一域名,不同端口                不允许
 
http://www.domain.com/a.js
https://www.domain.com/b.js        同一域名,不同协议                不允许
 
http://www.domain.com/a.js
http://192.168.4.12/b.js           域名和域名对应相同ip              不允许
 
http://www.domain.com/a.js
http://x.domain.com/b.js           主域相同,子域不同                不允许
http://domain.com/c.js
 
http://www.domain1.com/a.js
http://www.domain2.com/b.js        不同域名                         不允许

跨域常见解决方案

  • 通过JSONP跨域
  • document.domain + iframe 解决跨域
  • 跨域资源共享(CORS)
跨域资源共享(CORS)(cross-origin sharing standard )

MDN地址:developer.mozilla.org/zh-CN/docs/…

MDN定义:跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。

普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

预检请求 OPTIONS

对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)

简单请求

某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:

使用下列方法之一:

  • GET
  • HEAD
  • POST

没有人为设置该集合之外的其他首部字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (需要注意额外的限制)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

Content-Type 的值仅限于下列三者之一:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

阮一峰博客:www.ruanyifeng.com/blog/2016/0…

跨域的nginx解决

前端可直接访问的域名:frontEnd.baymax.com 需要转发的域名:proxyEnd.baymax.com

通过下面类似的配置,可以完成跨域的目的

server {
        listen  8300;
        server_name  http://frontEnd.baymax.com;
        root    /usr/share/nginx/html;

        location / {
                proxy_pass https://proxyEnd.baymax.com;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host proxyEnd.baymax.com;
                add_header 'Access-Control-Allow-Credentials' 'true';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
                add_header 'Access-Control-Allow-Headers' 'X-Requested-With, Content-Type';
                proxy_http_version 1.1;
                proxy_read_timeout 600s;
                proxy_send_timeout 600s;
        }
}