You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vertx SessionHandler每次请求均创建新会话问题求助

问题分析与修复方案

你的核心问题是跨域场景下Vert.x会话Cookie未被前端正确携带/识别,导致每次请求生成新会话,进而陷入登录循环。结合代码来看,主要有以下几个问题及对应修复方案:


问题根源

  1. 中间件顺序错误:SessionHandler在CorsHandler之前执行,跨域请求的OPTIONS预检会先触发无效会话创建,且跨域头未提前设置导致浏览器拒绝接受会话Cookie。
  2. Secure Cookie配置不匹配环境:本地用HTTP协议(http://localhost),但会话Cookie的SecureFlag设为true,浏览器会拒绝保存这类仅在HTTPS下生效的Cookie。
  3. 跨域头配置冲突:部分接口手动设置Access-Control-Allow-Origin: *,但开启allowCredentials=true时,该头必须是具体源,不能用通配符,否则浏览器会阻止凭证传递。
  4. 前端未携带凭证: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:05:04