webman (本地nginx反向代理域名 webman.lc)
react (vite, locahost:5173)
webman官方user插件
已经成功配置了文档中的 跨域中间件,get/post 请求除 session/cookie 外的数据都可以接收到,但是 session/cookie 获取不到,做了最简单的测试文件,get 设置 session,post 获取session,获取不到,看 network 标头,未发送任何cookie,在响应头的 set-cookie 那边会提示:此Set-Cookie标头未指定SameSite属性,默认 SameSite=Lax
注:如果开启 vite proxy,把请求地址换成 /api/,别的完全不动,就是成功的
下面写了个简单的测试,session 为 null
// 测试接口: http://webman.lc/app/user/login/test
public function test(Request $request) {
if ($request->method() === 'POST') {
return json(['code' => 1, 'method' => 'POST', 'data' => [
'session_value' => session('test-value'),
'info' => $request->post()
]]);
} elseif ($request->method() === 'GET') {
$value = $request->get('value');
$request->session()->set('test-value', $value);
return json(['code' => 1, 'method' => 'GET', 'data' => [
'session' => session('test-value'),
'value' => $value
]]);
}
}
// 前端测试
import axios from 'axios';
axios.defaults.withCredentials = true;
// 请求标头:PHPSID=923c68b641a8d9418bd18b92151f7972
const testGet = async () => {
try {
// 发送 GET 请求
axios.get('http://webman.lc/app/user/login/test?value=loginTest', {
withCredentials: true
}).then((json) => console.log(json));
} catch (error) {
console.error('Error testing cookie:', error);
}
};
const testPost = async () => {
try {
// 发送 POST 请求
axios.post('http://webman.lc/app/user/login/test', {
username: 'adelle25@example.org',
password: '123123'
}).then((json) => console.log(json));
} catch (error) {
console.error('Error testing cookie:', error);
}
};
// testGet();
testPost();
export default () => {
return <div>Check console for cookie info</div>;
}
// 中间件 plugin/user/app/middleware/
<?php
namespace plugin\user\app\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
class AccessControl implements MiddlewareInterface
{
public function process(Request $request, callable $handler) : Response
{
// 如果是options请求则返回一个空响应,否则继续向洋葱芯穿越,并得到一个响应
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
// 给响应添加跨域相关的http头
$response->withHeaders([
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => $request->header('origin', 'http://localhost:5173'),
'Access-Control-Allow-Methods' => $request->header('access-control-request-method', 'GET, POST, OPTIONS'),
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', 'Content-Type, Authorization, X-Requested-With'),
]);
return $response;
}
}
// 中间件配置 plugin/user/config/
<?php
use plugin\user\app\middleware\AccessControl;
return [
// 全局中间件
'' => [
// ... 这里省略其它中间件
AccessControl::class,
]
];
在前端 GET 请求设置 session 后,在 POST 请求获取 session
会发现 session 为 null
操作系统:macos
webman + webman-admin 最新版
你的问题主要在于跨域请求时的
SameSite
属性设置以及withCredentials
的使用。设置
SameSite
属性:在你的
webman
项目中,确保在设置session
的地方添加SameSite=None
和Secure
属性。例如:确保前后端都设置了
withCredentials
:在你的前端代码中,你已经设置了
withCredentials
,确保在所有请求中都包含此设置。修改 Nginx 配置:
确保你的 Nginx 配置中没有阻止跨域请求,并且允许发送
credentials
:确保
session
的正确设置:在 Webman 中,确保
session
配置正确,并且在设置session
时没有遗漏SameSite
属性:检查浏览器控制台:
打开浏览器控制台,检查网络请求的
Request Headers
和Response Headers
,确保Set-Cookie
头包含SameSite=None; Secure
属性,并且请求头包含Cookie
。确保 HTTPS:
如果你使用的是
SameSite=None
,需要确保你的站点使用 HTTPS,否则Secure
属性将无法生效。通过以上步骤,应该可以解决跨域请求时
session
和cookie
无法获取的问题。替你问的AI https://www.workerman.net/ai
谢谢,和chatgpt 4.o的回答一样,但是不能解决问题,它甚至重复了nginx 与中间件里标头的设置。。。中间件、credentials 这些能查到的设置都设置了,也没报错,就是session获取不到
排查了两天了,就是没办法解决 T T
除了 withCredentials、跨域http头外,还能怎么排查。。。
======
更新一下,似乎这些设置都是针对跨域请求,比如 a.site.com 与 b.site.com,我把前端访问地址从 localhost:5173 修改成了 front.webman.lc:5173 , 就能顺利获取 session cookie 了
跨站的话,这些设置似乎还不够,还需要 https 的相关配置?