浏览器跨域是为了安全问题而引入的同源策略
同源策略:
- 协议、主机名、端口中有一个不同时,浏览器判定两者不同源,从而产生跨域
请求正常发出和响应,但是浏览器会对响应校验
在跨域请求时默认不会带上 cookie(会话级别):
- xhr.withCredentials = true,Access-Control-Allow-Credentials: true(服务器不得设置 Access-Control-Allow-Origin 的值为 *,设置为 * 带不上凭证,Access-Control-Allow-Headers 和 Access-Control-Allow-Methods 也不能为 *)
- 将 Cookie 的 SameSite 值设为 None,Secure 值改为 true,并且升级为 https,我们就可以 跨域 使用 Cookie。
- 将 Cookie 的 SameSite 值设为 Lax/Strict,并且将前后端部署在同一台服务器下,我们就可以在同一站点使用 Cookie。
解决方案
网络:
CORS (Cross-Origin Resource Sharing) 校验规则 ^cf0cbe
简单请求:请求头部带上 Origin:域名,响应 Access-Control-Allow-Origin 等于这个域名或者 * 就通过校验
请求方法:GET、HEAD、POST。
请求头:Accept、Accept-Language、Content-Language、Content-Type。(修改或者添加后不是)
- Content-Type 仅支持:application/x-www-form-urlencoded、multipart/form-data、text/plain。
预检请求:options:请求带上 Origin 和方法和修改过的请求头
- 依赖服务端 / 后端在响应头中添加 Access-Control-Allow-* 头,告知浏览器端通过此请求
- Access-Control-Allow-Origin 表示允许的来源
- Access-Control-Allow-Methods 表示允许的请求方法
- Access-Control-Allow-Headers 表示允许的请求头
- Access-Control-Allow-Credentials 表示允许携带认证信息
反向代理
- 通过同源的服务端对请求做一个转发处理,比如开发中通过工具配置 proxy 等
JSONP
- 只支持 GET 请求。利用了浏览器加载 JavaScript 资源文件时不受同源策略的限制而实现跨域获取数据
- 前端注册函数,服务端返回函数表达式,参数中携带数据
DOM:
postMessage
- 即在两个 origin 下分别部署一套页面 A 与 B,A 页面通过 iframe 加载 B 页面并监听消息,B 页面发送消息
document.domain(手动修改,骗浏览器)
- 可将相同一级域名下的子域名页面的 document.domain 设置为一级域名实现跨域。
- 可将同域不同端口的 document.domain 设置为同域名实现跨域(端口被置为 null)。
数据:
- LocalStorage / SessionStorage /cookie 也会跨域
nginx 代理
nginx
server {
listen 80;
location / {
root /var/www/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15