PHP $_SESSION 数组在前端生产构建时为空,但在开发构建时不是
Posted
技术标签:
【中文标题】PHP $_SESSION 数组在前端生产构建时为空,但在开发构建时不是【英文标题】:PHP $_SESSION array is empty with frontend production build but NOT with developement build 【发布时间】:2021-12-10 09:35:30 【问题描述】:我有一个托管在 https://api.mydomain.abc
的后端,我正在开发一个使用 webpack 服务器的 vue/quasar CLI 前端。
当前端在开发模式下运行时,它由 webpack 网络服务器托管,前端代码中的 url 为 /api/index.php
格式。然后将 webpack 服务器配置为将它们代理到真正的后端 url:
devServer:
...,
proxy:
// proxy all requests starting with /api to avoid cors problems.
'/api':
target: 'https://api.mydomain.abc',
changeOrigin: true,
pathRewrite:
'^/api': '' //remove /api from the final url
,
在生产模式下运行时,前端由位于 https://www.mydomain.abc
的 nginx 服务器托管,前端的 URL 现在直接类似于 https://api.mydomain.abc
。
从现在开始,两种请求类型(开发和生产)都是相同的。 https://api.mydomain.abc
请求被同一个 NGINX 服务器监听,但现在作为反向代理工作,将它们重定向到带有 PHP 模块的 apache 服务器。这里有一个非常简单的纯 PHP 脚本,没有任何外部框架或库,它只是管理登录并在用户正确登录时从数据库返回一些动态值。
关键是在开发环境中一切正常,但在生产环境中,所有受登录保护的请求都失败了,因为 $_SESSION 数组为空!!
我完全不知道是什么导致了这种错误,因为两种环境的后端都是一样的。
更多信息:
在 apache 服务器中设置了 CORS 标头以允许来自 www.mydomain.abc(以及 mydomain.abc)的请求,并且没有任何 CORS 错误。 两种环境都使用https
协议访问后端
我的 PHP 脚本在脚本开头无条件运行 session_start()
我尝试了this answer,但没有观察到任何变化。
什么可能导致两种环境之间出现这种差异?除了 webpack 服务器之外,它们实际上是相同的。
【问题讨论】:
仔细检查一下:你在 webpack 服务器中是否有指令来为生产服务器执行代理? 对不起@KenLee,我想我没有正确地理解你。当前端托管到生产 Web 服务器 (NGINX) 时,不涉及 Webpack 服务器。 NGINX 不处理会话。它用作前端的静态 Web 服务器(在生产模式下部署时)和 api Web 服务器 (apache) 的反向代理。 apache 是管理会话的那个吗?关键是这两个环境(开发和产品)都是一样的,都共享相同的反向代理和相同的后端环境。唯一的区别是,在开发模式下,在一切之上还有另一个代理,即 webpack 服务器,它以某种方式使其与众不同。 嗯,这是从服务器发送到客户端的Set-Cookie
标头。应该从客户端发送到服务器的Cookie:
标头呢?
@vstm 是的,就是这样。 credentials: "include"
为fetch
成功。在开发过程中没有触发该问题,因为它是前端和后端之间的same-origin
环境,而不是cross-origin
。还很高兴注意到标头 Access-Control-Allow-Credentials: "true"
也需要设置到服务器端,如果不是 CORS 再次咬人的话。谢谢大家的帮助。如果你愿意,你可以回答,我会选择它。
【参考方案1】:
我会自己回答。问题在于,在开发过程中,浏览器位于 localhost url 中,向 localhost 服务器发出请求(webpack 服务器,然后将其代理到真正的 api 生产服务器,但浏览器不知道这一点)。这是浏览器的same-origin
环境,因此fetch
API 将凭据(phpsessioncookie)发送到服务器,因为这是same-origin
环境中的默认行为。
在生产环境中,webpack 服务器不参与其中,浏览器在(www.)mydomain.com
向api.mydomain.com
发出请求。这里的问题是,即使 (www.)mydomain.com
在 API Web 服务器中被设置为允许的来源,对于浏览器来说,它是一个 cross-origin
环境,这意味着 fetch
API 默认不发送凭据。 credentials:include
覆盖默认值并发送它们。
如果不存在,服务器端也需要标头Access-Control-Allow-Credentials: "true"
。
【讨论】:
以上是关于PHP $_SESSION 数组在前端生产构建时为空,但在开发构建时不是的主要内容,如果未能解决你的问题,请参考以下文章