#跨域

因为同源策略限制,所以 协议,域名,端口 有一个不同时需要跨域

有三个浏览器标签支持跨域加载资源

  • <img src=''>
  • <link href=''>
  • <script src=''>

跨域可以正常请求与响应,但是结果被浏览器拦截

#解决跨域问题

#CORS 跨源资源共享

服务器配置响应头Access-Control-Allow-Origin: <origin> | *具体域名或者全部

跨域请求会自动携带 Origin 请求头

例如 点击标题的 CORS MDN 链接后打开控制台查看请求的 js 文件响应头,会找到 CORS 属性

#简单请求

  • GETPOSTHEAD
  • 请求头 仅限AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type仅限内容为application/x-www-form-urlencodedmultipart/form-datatext/plain

#非简单请求

非简单请求时浏览器会发起一个 OPTIONS 方法(状态码可以是 204 No Content) 请求检查服务器是否支持 CORS,即预检请求 Preflight

会携带三个请求头

例如: 直接本网站通过控制台发送即可

await fetch('https://httpbin.org/cors', {
  headers: { mehod: 'PUT' },
})

#CORS 多域名跨域

因为仅跨域请求携带 Origin 请求头

所以通过请求头 Origin 在服务器判断

  • 如果没有则不配置
  • 如果有则配置对应域名:Access-Control-Allow-Origin: <Origin>

通过响应头 vary:Origin 对不同域名来源缓存,防止缓存了 a 域名,b 域名访问也是 a 域名的内容

#反向代理

开发环境:webpack proxy 生产环境:nginx

#jsonp

通过<script src=''>请求,所以只能是GET请求

实现:

  • 前端传给后端函数名 name
  • 后端返回 name(JSON.stringify(data))
  • script 标签加载:<script src="http://localhost:3000?callback=name"></script>

script 标签加载后会执行 js 文件,就是执行name(JSON.stringify(data)),前端就可以在 name 函数内拿到 data

#应用场景

除了跨域还有 webpack 加载 chunk 模块

默认不携带 需要配置浏览器与服务器

  • 浏览器 fetch 配置属性credentials: include
  • 服务器配置响应头 access-control-allow-credentials: trueaccess-control-allow-origin: <origin>不能为*

例如:

await fetch('https://httpbin.org/cookies/set/a/3', {
  headers: { 'content-type': 'application/json' },
  credentials: 'include',
})