PHP $_SESSION 数组在前端生产构建中为空,但在开发构建中不存在
PHP $_SESSION array is empty with frontend production build but NOT with developement build
我在 https://api.mydomain.abc
中托管了一个后端,并且我正在使用 vue/quasar CLI 开发一个使用 webpack 服务器的前端。
当前端是 运行 开发时 mode 它由 webpack web 服务器托管,前端代码中的 urls 具有 /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
}
}
}
},
当 运行 在生产中时 mode 前端由位于 https://www.mydomain.abc
的 NGINX 服务器托管,前端中的 urls 现在直接像 https://api.mydomain.abc
.
从现在开始,两种请求类型(开发和生产)都相同。 https://api.mydomain.abc
请求由同一个 NGINX 服务器侦听,但现在作为反向代理工作,将它们重定向到具有 PHP mod 的 apache 服务器。这里有一个非常简单的普通 PHP 脚本,没有任何外部框架或库,它只管理登录和 return 如果用户正确登录,来自数据库的一些动态值。
重点是在开发环境中一切正常,但在生产环境中所有登录保护请求都会失败,因为 $_SESSION 数组为空!!
我完全不知道是什么导致了这类错误,因为两种环境的后端都是一样的。
更多信息:
- CORS headers 在 apache 服务器中设置为允许来自 www.mydomain.abc(以及 mydomain.abc)的请求,并且没有任何 CORS 错误。
- 两种环境都使用
https
协议访问后端
- 我的 PHP 脚本在脚本开始时无条件运行
session_start()
我已经尝试 this answer 但没有发现任何变化。
是什么导致了两种环境之间的差异?除了 webpack 服务器之外,它们实际上是相同的。
我会自己回答。问题是在开发过程中,浏览器在本地主机 url 中,向本地主机服务器(webpack 服务器,然后将其代理到真正的 api 生产服务器,但浏览器没有意识到这一点).这是浏览器的 same-origin
环境,因此 fetch
API 将凭据 (phpsessioncookie) 发送到服务器,因为这是 same-origin
环境中的默认行为。
在生产环境中,webpack 服务器未参与其中,浏览器在 (www.)mydomain.com
中向 api.mydomain.com
发出请求。这里的问题是,即使 (www.)mydomain.com
在 API 网络服务器中被设置为允许的来源,对于浏览器来说它是一个 cross-origin
环境,这意味着 fetch
API 默认情况下不发送凭据。 credentials:include
覆盖默认值并发送它们。
如果 header Access-Control-Allow-Credentials: "true"
不存在,服务器端也需要它。
我在 https://api.mydomain.abc
中托管了一个后端,并且我正在使用 vue/quasar CLI 开发一个使用 webpack 服务器的前端。
当前端是 运行 开发时 mode 它由 webpack web 服务器托管,前端代码中的 urls 具有 /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
}
}
}
},
当 运行 在生产中时 mode 前端由位于 https://www.mydomain.abc
的 NGINX 服务器托管,前端中的 urls 现在直接像 https://api.mydomain.abc
.
从现在开始,两种请求类型(开发和生产)都相同。 https://api.mydomain.abc
请求由同一个 NGINX 服务器侦听,但现在作为反向代理工作,将它们重定向到具有 PHP mod 的 apache 服务器。这里有一个非常简单的普通 PHP 脚本,没有任何外部框架或库,它只管理登录和 return 如果用户正确登录,来自数据库的一些动态值。
重点是在开发环境中一切正常,但在生产环境中所有登录保护请求都会失败,因为 $_SESSION 数组为空!!
我完全不知道是什么导致了这类错误,因为两种环境的后端都是一样的。
更多信息:
- CORS headers 在 apache 服务器中设置为允许来自 www.mydomain.abc(以及 mydomain.abc)的请求,并且没有任何 CORS 错误。
- 两种环境都使用
https
协议访问后端 - 我的 PHP 脚本在脚本开始时无条件运行
session_start()
我已经尝试 this answer 但没有发现任何变化。
是什么导致了两种环境之间的差异?除了 webpack 服务器之外,它们实际上是相同的。
我会自己回答。问题是在开发过程中,浏览器在本地主机 url 中,向本地主机服务器(webpack 服务器,然后将其代理到真正的 api 生产服务器,但浏览器没有意识到这一点).这是浏览器的 same-origin
环境,因此 fetch
API 将凭据 (phpsessioncookie) 发送到服务器,因为这是 same-origin
环境中的默认行为。
在生产环境中,webpack 服务器未参与其中,浏览器在 (www.)mydomain.com
中向 api.mydomain.com
发出请求。这里的问题是,即使 (www.)mydomain.com
在 API 网络服务器中被设置为允许的来源,对于浏览器来说它是一个 cross-origin
环境,这意味着 fetch
API 默认情况下不发送凭据。 credentials:include
覆盖默认值并发送它们。
如果 header Access-Control-Allow-Credentials: "true"
不存在,服务器端也需要它。