前后端跨域问题
啥是跨域
跨源资源共享(CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。
跨源 HTTP 请求的一个例子:运行在 https://domain-a.com 的 JavaScript 代码使用 XMLHttpRequest 来发起一个到 https://domain-b.com/data.json 的请求。
出于安全性,浏览器限制脚本内发起的跨源 HTTP 请求。例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。
为什么会跨域
说到跨域不得不谈的就是浏览器的同源策略,跨域也是因为浏览器这个机制引起的,这个机制的存在还是在于安全。
什么是源
Web 内容的源由用于访问它的 URL 的方案 (协议),主机 (域名) 和端口定义。只有当方案,主机和端口都匹配时,两个对象具有相同的起源。
同源不同源一句话就可以判断:就是 url 中 scheme host port 都相同即为同源。
URL 结构
URL 代表着是统一资源定位符(Uniform Resource Locator)。URL 无非就是一个给定的独特资源在 Web 上的地址。
URL 有如下结构组成:
Scheme 或者 Protocol, 常见的就是 http 或者 https
Domain Name 也叫做 host 域名
port 端口号
Parameters 参数
Anchor 锚点,一般用于定位位置
同源不同源举例
就是 url 中 scheme host port 都相同即为同源。 下面是几个不同源的例子, 如果访问就会产生跨域问题.
前端域名 | 后端域名 | 原因 |
---|---|---|
https://example.com/ | http://example.com/api | 协议不一样 |
http://example.com | http://api.example.com | host 不一样 |
http://example.com | http://example.com:8080 | 端口不一样 |
跨域问题的症状
有跨域问题
正常情况
后端解决方案
三、后端解决方案
后端框架也很多,实现原理差不多,都是修改下相应头。以常用的 Java SpringCloud 和 nodejs koa 框架为例。
Http 协议 CORS 头
跨域其实也是 http 层面上可以解决的问题,后端解决也是比较简单的,也是项目常见的解决手法。
CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的 HTTP 头组成,这些 HTTP 头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。
同源安全策略 默认阻止“跨域”获取资源。但是 CORS 给了 web 服务器这样的权限,即服务器可以选择,允许跨域请求访问到它们的资源。其实就是一些 Header 头:
1 | Access-Control-Allow-Origin 指示请求的资源能共享给哪些域。 |
1 |
|
运维解决方案
Nginx ingress 配置
增加注解
1 | nginx.ingress.kubernetes.io/cors-allow-credentials: 'true' |
Nginx 配置
使用 proxy_pass 转发
此方法是将后端地址反代到前端的一个 location, 这样就是同源了.
1 | location /api { |
使用 Nginx 增加 Header
1 | server { |
常见问题
后端服务和 Nginx 同时处理了跨域
跨域问题后端和 Nginx 不要同时处理, 不然会报错:
这个时候删除 Nginx 上的 Access-Control-Allow-Origin 配置即可, 建议后端和 Nginx 不要同时配置跨域.
Header 不在允许的列表中
出现跨域问题的时候, 可以在浏览器的控制台看到详情, 比如下图提示 x-xxx-client-version
这个 header 不在 Access-Control-Allow-Headers
中, 那你再手动加一下就行了.