Vertx SessionHandler每次请求均创建新会话问题求助
问题分析与修复方案
你的核心问题是跨域场景下Vert.x会话Cookie未被前端正确携带/识别,导致每次请求生成新会话,进而陷入登录循环。结合代码来看,主要有以下几个问题及对应修复方案:
问题根源
- 中间件顺序错误:
SessionHandler在CorsHandler之前执行,跨域请求的OPTIONS预检会先触发无效会话创建,且跨域头未提前设置导致浏览器拒绝接受会话Cookie。 - Secure Cookie配置不匹配环境:本地用HTTP协议(
http://localhost),但会话Cookie的SecureFlag设为true,浏览器会拒绝保存这类仅在HTTPS下生效的Cookie。 - 跨域头配置冲突:部分接口手动设置
Access-Control-Allow-Origin: *,但开启allowCredentials=true时,该头必须是具体源,不能用通配符,否则浏览器会阻止凭证传递。 - 前端未携带凭证:Next.js请求接口时未配置携带Cookie的参数,导致登录后的会话Cookie不会被发送到Vert.x服务。
具体修复步骤
1. 调整中间件执行顺序
将CorsHandler移到SessionHandler之前,确保跨域预检先被处理:
@Override public void start(Promise<Void> promise) throws Exception { Router router = Router.router(vertx); // 先配置跨域处理 CorsHandler corsHandler = CorsHandler.create() .addOrigin("http://localhost:3000") .allowedMethod(HttpMethod.POST) .allowedMethod(HttpMethod.GET) .allowedMethod(HttpMethod.OPTIONS) .allowedHeader("Content-Type") .allowCredentials(true); router.route().handler(corsHandler); // 再配置会话处理 LocalSessionStore sessionStore = LocalSessionStore.create(vertx); SessionHandler sessionHandler = SessionHandler.create(sessionStore) .setCookieSecureFlag(false) // 本地HTTP环境改为false,生产HTTPS再改回true .setCookieHttpOnlyFlag(true) .setCookieSameSite(CookieSameSite.LAX) // 跨域场景下LAX比NONE更安全且能正常传Cookie .setSessionCookiePath("/") .setSessionCookieName("vid"); // 显式设置Cookie名称,便于调试 router.route().handler(sessionHandler); // 后续路由配置... }
2. 移除零散的跨域头设置
删除loginHandler和createLinkToken中手动添加的Access-Control-Allow-*头,这些由CorsHandler统一处理即可,避免配置冲突。
3. 前端请求配置携带凭证
在Next.js中调用Vert.x接口时,必须开启凭证携带:
- fetch示例:
// 登录请求 fetch('http://localhost:8082/v/sign-in', { method: 'POST', credentials: 'include', // 关键配置 headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ textCode: 'xxx' }) }) // 仪表盘受保护接口请求 fetch('http://localhost:8082/api/do-protected-work', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(...) })
- axios示例:
axios.post('http://localhost:8082/v/sign-in', { textCode: 'xxx' }, { withCredentials: true }) axios.post('http://localhost:8082/api/do-protected-work', {...}, { withCredentials: true })
4. 优化会话校验逻辑(可选)
将loginHandler中的302重定向改为返回401状态码,让前端自行处理登录跳转,跨域场景下更可靠:
Handler<RoutingContext> loginHandler = ctx -> { Session session = ctx.session(); String sessionValue = session.get("my-session"); if(sessionValue != null){ ctx.next(); } else { ctx.response() .setStatusCode(401) .end(); } };
内容的提问来源于stack exchange,提问作者ZiCode
相关产品推荐
相关产品推荐

