浏览器 跨域问题console 报错
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource athttps://example.com/
Access to fetch at ‘https://example.com’ from origin ‘http://localhost:3000’ has been blocked by CORS policy.
如果你遇到这些报错,就是跨域问题。
Origin & Cross-origin
判断是否跨域 看三个指标:scheme,host,和port 。例如,https://example.com http://example.com 是不用域的,因为前者是http scheme 后者是https.
跨域的风险
如果 CORS 不存在,网络浏览器允许各种各样的跨源请求。
想象一下,我在我的网站 evil. com 上有一个带有 <script> 的页面。表面上它看起来像一个简单的页面,在那里你可以读到一些有用的信息。但是在 <script> 中,我特别编写了一些代码,它们将向银行的 DELETE / 帐户端点发送一个特殊编写的请求。加载页面后,执行 JavaScript,然后一个 AJAX 调用访问银行的 API。
想象一下,当你在网页上阅读一些信息时,你收到一封来自你银行的电子邮件,你已经成功地删除了你的帐户。我知道我知道… … 如果银行真的那么容易。我跑题了。
为了让我邪恶的 <script> 工作,作为请求的一部分,你的浏览器还必须从银行网站上发送你的证书 (cookies)。这样银行的服务器就能识别你的身份,并知道该删除哪个账户。
- 让我们看看一个不同的,不那么邪恶的场景。
我想找到那些为 Awesome Corp 工作的人,他们的内部网站在 intra.Awesome-Corp.com 上。在我的网站上,dangerous.com i got an <img src = “https://intra.awesome-corp. com/avatars/john-doe.png”> 。
对于那些没有使用 intra.awesome-corp.com 的会话活动的用户,虚拟化身不会渲染 - 它会产生一个错误。但是,如果你登录了 Awesome 公司的内部网,一旦你打开了 dangerous.com 网站,我就知道你有权限访问。
这意味着我将能够得到一些关于你的信息。虽然对我来说制造一个攻击绝对是很困难的,但是你可以访问 Awesome 公司的 仍然是一个潜在的攻击风险。
同源策略
同源策略 规则集
标签 Cross-origin 注意
<iframe> 允许 embeds 看情况X-Frame-Options
<link> 允许 embeds 适当的 可能需要
<form> 允许 write Cross-origin write 是很常见的
<img> 允许 embeds 通过 JavaScript 进行跨源读取,并将其加载到 是被禁止的
<audio> / <video> 允许 embeds
<script> 允许 embeds 可能会禁止访问某些 api
CORS
CORS(cross origin resource sharing ) 诞生的目标是放宽同源政策和微调跨源接入。 该机制将子资源访问分为三类:
- cross-origin write
指连接,重定向,表单提交。 还有一种是preflight请求的东西,可以微调cross -origin write 。 - cross-origin embeds
通过 <script> ,<link>,img,video,audio ,iframe, embed 等标签加载的子资源。 - cross-orgin reads
通过ajax/fetch加载的子资源。通常情况下,这些在浏览器中事被blocked的。
prefilght request
复杂请求 即是 options 请求通过了也会拦截。
现代浏览器定义的 复杂请求
- 一个使用GET、POST或HEAD以外的方法的请求
- 请求中包含除Accept、Accept-Language或Content-Language以外的头信息。
- 请求中的Content-Type头值不是application/x-www-form-urlencoded, multipart/form-data, 或text/plain。
nginx 配置cookie
正常的跨域解决就是网上搜的,然后有一点就是允许转发携带cookie,这个应该是现代浏览器加了校验,解决方案网上看了三个:
- 客户端解决方案 (测试可以)
主要是 SameSite=None; Secure,具体cookie 设置
document.cookie = ‘cookie2=value2; SameSite=None; Secure’; - 服务器端
模式是一样的,只是写入cookie的模式不一样,以下是node 的参考
response.setHeader(‘set-cookie’, ‘cookie1=value1; SameSite=Lax’,
‘cookie2=value2; SameSite=None; Secure’,
]); - 改用https 方式
注意 :对于SameSite=None 同时也需要设置Secure,同时我们需要改用https,而且注意测试的时候不要使用无痕模式,chrome无痕模式默认是阻止三方cookie的
所以也是不能测试的,(https://samesite-sandbox.glitch.me/ 是一个好工具,方便测试是否生效)对于web 推荐使用js-cookie 包装的比较完整,使用上简单
2,3方式可能有些重叠,需要验证。。。。。。
总结:
W3C标准规定,http请求头的origin(源地址)与目的地址在协议(http1.1,https等),端口,域名(ip)任何一个不一致就会触发跨域拦截机制。
为什么只有ajax会触发跨域?
其实这个问题问的并不好,回答这个问题前,我们要了解跨域可以简单的分为两种:简单请求和复杂请求
- 简单请求 :
- http请求方法的值限于三者之一:get,put,post;
- Content-Type的值仅限于三者之一:text/plain,multipart/form-data,application/x-www-form-urlencoded;
除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:
Accept Accept-Language Content-Language Content-Type (需要注意额外的限制) DPR Downlink Save-Data Viewport-Width Width 123456789 - 复杂请求
除了简单请求都是复杂请求,我们大多数时候都是 ajax请求的Content-Type:application/json 这样的复杂请求导致的。
简单请求如果设置了Authentication认证header也会让请求“升级”为复杂请。
简单请求相比于复杂请求少了一步 预检请求,也就是http的OPTIONS请求
这些规则在现代浏览器都是有实现的。