Blog

怎么算跨域

time: 2018.2.x

update: 2018.11.08
update: 2020.12.15
update: 2021-11-25 17:18:03
update: 2022-07-26 15:20:35

背景

本地java tomcat 服务器, 8080 端口;
前端 roadhog 服务器, 8000 端口。

现在前后端分离,开发时需要获取后台数据,所以需要跨域。

1 跨域

出现的目的:解决数据安全问题,不允许修改和使用非同域数据
跨域网络交互方式:

  1. 跨域嵌入:比如 link, iframe 等,是允许的
  2. 跨域读:不被允许
  3. 跨域写:表单提交及重定向,是允许的

三要素:端口、协议、ip(域名)
哪些场景受跨域限制:xhr, fetch, cookie
哪些场景不受跨域限制:script, img, link, video, iframe 可以加载资源,资源会自执行,但是我们不能去读取它

2 跨域解决方案

2.1 jsonp

jsonp 利用了script标签没有同源策略限制的漏洞;

实现方案:
首先声明一个函数,假如叫: var loadJson = function(data){} ,然后服务器返回的json数据字符串用一个函数字符串包裹起来,比如 loadJson({hello:"world"}),然后解析返回数据。具体执行数据,在loadJson 里面执行。

2.2 cors

服务器端设置响应头

res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
res.setHeader("Access-Control-Allow-Methods","OPTIONS,GET,POST,PUT,DELETE");
res.setHeader("Content-Type: text/html","charset=UTF-8");

cors 请求方式

  1. 简单请求:直接发起一个 http 请求
  2. 复杂请求:options + http 请求

简单请求定义:

  1. 使用 get, post, head,不包含 put, delete
  2. http 安全 header:Accept, Accept-Language, Content-Type 等

2.3 chrome禁用同源策略

也可以直接启动禁用同源的浏览器,比如谷歌:

--disable-web-security --user-data-dir

为什么要加 --user-data-dir 参数呢?
答:其实这是chrome更新版本49之后的bug,之前都可以不需要这个参数直接启动,现在必须要加上这个参数

2.4 服务器转发

proxy: {
    "/plmPortal/": {
      "target": "http://plmcloud.yonyou.com/plmPortal/",
      "changeOrigin": true,
      "pathRewrite": { "^/plmPortal/" : "" }
    }
}

服务器转发:使用nginx做转发代理,通常这个服务器是自身项目运行所在的服务器

2.5 document.domain

前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域 (基本没有多大用)

应用场景:2个子域名下的发起访问

aaa.xxx.com
bbb.xxx.com

可以修改为 document.domain = "xxx.com"; ,即可实现跨域

2.6 浏览器插件

可以通过浏览器插件拦截 response,增加响应头

3 iframe 跨域

time: 2021-11-25 17:15:44

iframe 跨域加载跨域资源,但是不能通过 iframe.contentWindow 访问跨域资源,只能判断 iframe 是否聚焦,可以通过 postMessage 实现跨域通信

在 chrome 80 之后, cookie 的 SameSite 被默认设置为 Lax 了,之前其值为 None,为 None 表示跨域也会携带 cookie,Lax 表示被 iframe 跨域嵌入的页面不会传递 cookie,即嵌入的页面无法进行需要 cookie 鉴权的服务

解决方案:

  1. SameSite 显示设置为 None,同时设置 Secure 属性,即 Set-Cookie: flavor=choco; SameSite=None; Secure
  2. 采用 token 代替 cookie 实现鉴权,token 即为手动管理的 cookie

参考文章

mdn 浏览器的同源策略