什么是跨域
我们通常所说的跨域,是指由浏览器同源策略限制的一类请求场景。是指浏览器不能执行其他网站的脚本。是浏览器对JavaScript实施的安全限制。
什么是同源策略
所谓同源是指"协议+域名+端口"三者相同;即便是两个不同的域名指向同一个ip地址,也非同源
特别注意两点:
- 如果是协议和端口造成的跨域问题“前台”是无能为力的。
- 在跨域问题上,域仅仅是通过“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;
}
}