首页 » SEO优化 » phpallowcredentials技巧_No AccessControlAllowOrigin header跨域问题踩坑记

phpallowcredentials技巧_No AccessControlAllowOrigin header跨域问题踩坑记

访客 2024-11-18 0

扫一扫用手机浏览

文章目录 [+]

首先,只有 Web 浏览器才会产生跨域,这是由于浏览器的同源策略在限定。
同源策略便是 [域名(又称为主机 host),端口(port),协议(protocol)] 要统一,否则就会被浏览器剖断为跨域,然后谢绝要求。
但是严格的说,浏览器并不是谢绝所有的跨域要求,实际上谢绝的是跨域的读操作。

同源策略并不是不好,它在一定程度上担保了浏览器的安全,只是无法适应当代的潮流,在工程做事化后,不同职责的做事分散在不同的工程中,每每这些工程的域名是不同的,但一个需求可能须要对应到多个做事,这时便须要调用不同做事的接口。

phpallowcredentials技巧_No AccessControlAllowOrigin header跨域问题踩坑记

phpallowcredentials技巧_No AccessControlAllowOrigin header跨域问题踩坑记
(图片来自网络侵删)
哪些情形下会产生跨域 ?

什么是 CORS ?

跨域资源共享(CORS) 是一种机制,它利用额外的 HTTP 头来见告浏览器 让运行在一个 origin (domain) 上的 Web 运用被答应访问来自不同源做事器上的指定的资源。
当一个资源从与该资源本身所在的做事器不同的域、协议或端口要求一个资源时,资源会发起一个跨域 HTTP 要求。
比如,站点 http://domain-a.com 的某 HTML 页面通过 <img> 的 src 要求 http://domain-b.com/image.jpg。
网络上的许多页面都会加载来自不同域的 CSS 样式表,图像和脚本等资源。
出于安全缘故原由,浏览器限定从脚本内发起的跨源 HTTP 要求。
例如,XMLHttpRequest 和 Fetch API 遵照同源策略。
这意味着利用这些 API 的 Web 运用程序只能从加载运用程序的同一个域要求 HTTP 资源,除非相应报文包含了精确 CORS 相应头。

跨域资源共享( CORS )机制许可 Web 运用做事器进行跨域访问掌握,从而使跨域数据传输得以安全进行。
当代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )利用 CORS,以降落跨域 HTTP 要求所带来的风险。

不过呢,并不一定是浏览器限定了发起跨站要求,也可能是跨站要求可以正常发起,但是返回结果被浏览器拦截了。

在“上古时期”,办理跨域有很多黑科技,什么 JSONP 啊,window.name 啊,document.domain 啊等等都用上了,但当代用的基本都是CORS跨域,以是上述方法在这里就不谈论了。

由上述可知,实现 CORS 通信的关键是做事器。
只要做事器实现了 CORS 接口,就可以跨源通信。

虽然事情重心在后端,但是作为前端,也要理解这方面的知识,否则就会涌现204预要求,然后后端没处理,就甩锅给前真个情形。

下面先容一些 CORS 过程中常见的 HTTP 相应头(Response Headers)。

什么是 Access-Control-Allow-Origin ?

这是 HTTP 相应首部中的一个字段,

详细魄式是: Access-Control-Allow-Origin: <origin> | 。

个中,origin 参数的值指定了许可访问该资源的外域 URI。
对付不须要携带身份凭据的要求,做事器可以指定该字段的值为通配符,表示许可来自所有域的要求。

如果做事端指定了详细的域名而非,那么相应首部中的 Vary 字段的值必须包含 Origin。
这将见告客户端:做事器对不同的源站返回不同的内容。
例如:

// 只相应来自 http://mozilla.com 的要求Access-Control-Allow-Origin: http://mozilla.com什么是 Access-Control-Allow-Methods ?

该字段必需,它的值是逗号分隔的一个字符串,表明做事器支持的所有跨域要求的方法。
把稳,返回的是所有支持的方法,而不单是浏览器要求的那个方法。
这是为了避免多次"预检"要求。

详细魄式是:Access-Control-Allow-Methods: <method>[, <method>]

什么是 Access-Control-Allow-Headers ?

可支持的要求首部名字。
要求头会列出所有支持的首部列表,用逗号隔开。

如果浏览器要求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。
它也是一个逗号分隔的字符串,表明做事器支持的所有头信息字段,不限于浏览器在"预检"中要求的字段。

详细魄式是:Access-Control-Allow-Headers: <header-name>[, <header-name>]

什么是 Access-Control-Allow-Credentials ?

该字段可选。
它的值是一个布尔值,表示是否许可发送 Cookie。
默认情形下,Cookie 不包括在 CORS 要求之中。
设为 true,即表示做事器明确容许,Cookie 可以包含在要求中,一起发给做事器。

浏览器的正常要乞降回应

一旦做事器通过了"预检"要求,往后每次浏览器正常的 CORS 要求,就都跟大略要求一样,会有一个 Origin 头信息字段。
做事器的回应,也都会有一个 Access-Control-Allow-Origin 头信息字段。

好了,铺垫完成,接下来要说说我踩的坑了。

问题实记项目背景

公司因历史遗留,同时存在3种后端措辞:Java,PHP,Node.js,由于后端同事都不懂 Node.js,以是 Node 项目一贯是前端掩护。
老项目用的是 Koa 框架,之前我在上面写逻辑,上传图片是没有问题的,直到我用了 Nest 框架重构,将后台管理系统的逻辑拆分解耦出来。

踩坑过程

新项目统统要求都正常,本地跑的时候也正常,但是到了线上,只有上传图片不正常。
每次上传都会预要求一次 204 OPTIONS,这一步没问题,但接下来的 POST 要求就有问题了:

我一看掌握台的信息,结合多年的开拓履历(实在并没有),这不便是跨域嘛,于是看代码,main.ts 中已经有了 app.enableCors(),百思不得其解,于是 Google,创造也有人碰着过类似的问题,说是 Nest 某些版本在线上环境无法精确利用 CORS,然后就形成了下列代码:

但是,并没有什么卵用,调试了好一下子才把稳到相应头是 nginx 返回的,然后就像创造新大陆一样屁颠屁颠的找运维老大:代码里面已经设置了 CORS 跨域了,是不是被 nginx 拦截了?(公司的做事器通过 nginx 做负载均衡,然后才到 node)

然后运维老大很合营的帮我配置了 nginx 的跨域,然后就悲剧了,连 OPTIONS 都过不去:

掌握台的大存问思是 CORS 规则冲突了,只能利用一种。

以是这个问题实在和 nginx 没有什么关系,运维大佬看了访问日志,说是 OPTIONS 要求是相应了的,但是到 POST 要求的时候就断开连接了,然后让我试试直接访问端口,于是掌握台又涌现了如下信息:

唔,大存问思是,源头是 https 协议的话,就不能要求 http 协议的资源。

于是我把网站上的 https 换成 http,就涌现了如下信息:

我就以为很奇怪,由于本地开拓的时候,是能正常上传图片的。
唯一不同的地方就在于,线上利用的是 pm2 进程管理工具,而我本地用的是自带的 nodemon。
为了验证我的预测,于是自己的电脑上也装了 pm2,然后跑起来,然后就。


Bug 果真复现了。

于是让运维大佬不用 pm2 直接用 nodemon 启动试试,然后折腾我良久的跨域问题就“办理了”。
为什么打引号呢,由于运维大佬并不是很想用 nodemon 来管理进程,紧张是如果做事器宕机,不能自动拉起,战役还远没有结束。

然后我就环绕着 pm2 连续探索,把官方文档看了个遍,也没找到关键点,忧郁之下,只好检讨的 pm2 启动配置,然后把稳到这个:

这是当初我为了输出日志的时候,更新了文件,防止被 pm2 监听到,导致做事一贯重启所做的方法。
然后就想到了,我上传图片的时候,是先在硬盘保存,然后读取 Buffer 流,然后再上传到 oss,末了删掉硬盘的图片,核心代码如下:

以是我就在想,是不是由于上传的时候,存本地的图片触发了 pm2 的监听,导致做事重启,以是就会报 net::ERR_CONNECTION_RESET,于是我改成了临时目录 const uploadCachePath = '/tmp/assets/uploads'; (Mac OS、Linux 都有这个目录),然后 pm2 启动,上传,成功。

至此,折磨了我近一周的 Bug 终于修复,结果和跨域没有半毛钱关系。

插曲

有读者可能把稳到 /tmp/assets/uploads 路径,假如同事用的是 Windows 系统开拓咋办?这个我自然也想到了,于是改了 pm2 的启动项:

可是无论若何改,依然会触发上述 Bug,由于做事器同时跑着 2 个 Node 项目,另一个项目也有自己的 pm2 启动项,以是觉得这个配置被另一个覆盖了,pm2 彷佛是全局的。
如果有其他大神深入理解过 pm2 的可以指示一下。

以是和运维大佬谈论了一下,给我开了权限,就暂时用这个临时目录,待往后找到更好的办理方案再优化,反正目前这个项目也只有我一人在掩护。

碰着的其他场景1. 做事器宕机

就在我刚找到办理方案的时候,我带的小弟跑过来问我是不是动了配置文件,老项目怎么都跨域了。
我去看他的掌握台,确实有 Access to ... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. 的信息,由于刚踩的坑,何况我也没动过配置文件,以是以为这肯定不是跨域问题。
然后我看了做事器的日志,创造一贯在重启,由于有个模块他没同步上去,只同步了路由文件,导致路由找不到对应的函数,做事就一贯在报错重启,根本就没处理要求。
于是让他把代码重新上传,问题办理。

以是个人预测(由于没有权限看做事器的配置),这次跨域是 nginx 代理的时候,由于访问不到 Node 做事,以是自然而然地就读不到 CORS 配置,然后报跨域缺点。

2. Axios 的自行检讨

Axios 创建实例时,有个字段须要把稳:

如果不设为 false,则会得到下面报错:

缘故原由便是前面提到的 Access-Control-Allow-Credentials 字段,CORS 要求默认不发送 Cookie 和 HTTP 认证信息。
如果要把 Cookie 发到做事器,一方面要做事器赞许:

Access-Control-Allow-Credentials: true

另一方面,开拓者必须在 AJAX 要求中打开 withCredentials 属性,也便是 Axios 默认打开的 withCredentials: true。

否则,纵然做事器赞许发送 Cookie,浏览器也不会发送。
或者,做事器哀求设置 Cookie,浏览器也不会处理。

但是,如果省略withCredentials设置,有的浏览器还是会一起发送 Cookie。
这时,须要显示关闭 withCredentials: false。

须要把稳的是,如果要发送 Cookie,Access-Control-Allow-Origin 就不能设为星号,必须指定明确的、与要求网页同等的域名。
同时,Cookie 依然遵照同源政策,只有用做事器域名设置的 Cookie 才会上传,其他域名的 Cookie 并不会上传,且(跨源)原网页代码中的 document.cookie 也无法读取做事器域名下的 Cookie。

总结

由上述可以总结,在后端配置了 CORS 的情形下,还会造成 Access to ... has been blocked by CORS policy ... 的情形大致有:

做事器溘然重启,导致代理做事器转发中断;做事器宕机,导致代理做事器读不到 CORS 配置;Axios 等要求插件设置了withCredentials: true,导致先行验证并拦截了要求;

有些时候,浏览器掌握台给出的缺点信息,不一定能真正地指出问题的所在,做为前端,还须要多去理解一些更实质的东西。

标签:

相关文章

i1协议助力国网迈向全球能源互联网

随着全球能源互联网的快速发展,我国国家电网公司(以下简称“国网”)积极响应国家战略,深入推进能源互联网建设。在此背景下,i1协议作...

SEO优化 2024-12-26 阅读0 评论0

HTML5,引领网页设计新时代

随着互联网技术的不断发展,网页设计语言也在不断更新换代。在众多网页设计语言中,HTML5因其强大的功能、丰富的API和良好的兼容性...

SEO优化 2024-12-26 阅读0 评论0

HDC语言,探索未来编程的新方向

随着科技的飞速发展,编程语言作为连接人与机器的桥梁,其重要性日益凸显。在众多编程语言中,HDC语言以其独特的优势,成为探索未来编程...

SEO优化 2024-12-26 阅读0 评论0

GRID语言,未来编程的基石

随着科技的发展,编程语言作为人类与计算机沟通的桥梁,其重要性不言而喻。在众多编程语言中,GRID语言凭借其独特的优势,逐渐成为未来...

SEO优化 2024-12-26 阅读0 评论0