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

如何在TSOA接口中设置跨子域共享的认证Cookie?

在TSOA + Express中设置跨子域共享的认证Cookie

问题描述

我基于Express搭建了后端服务,用TSOA定义接口。当前登录接口直接返回认证Token给前端存储,但现在有一个部署在同主域子域名下的第二个应用,需要共享这套认证体系,所以打算通过设置Cookie来实现Token的跨应用共享。

现有登录接口代码:

@Route('auth')
@Tags('Auth')
export class AuthController extends Controller {
  @SuccessResponse('200', 'Returns Token')
  @Post('/login')
  public async login(@Body() body: TokenRequest): Promise<TokenResponse> {
    // ... 登录逻辑实现
    return token
  }
}

我尝试注入Express的Response对象来设置Cookie,但无法成功获取;试过TSOA Controller基类的setHeader方法也没有效果,不知道正确的实现方式是什么。


解决方案

正确获取Express Response对象并设置跨子域Cookie

TSOA支持两种方式获取Express的Response实例,进而设置跨子域Cookie:

方式1:使用@Response()装饰器注入

确保从tsoa导入@Response()装饰器,同时将参数类型指定为Express的Response:

import { Controller, Route, Tags, Post, Body, SuccessResponse, Response } from 'tsoa';
import { Response as ExpressResponse } from 'express';
import { TokenRequest, TokenResponse } from './your-types-file';

@Route('auth')
@Tags('Auth')
export class AuthController extends Controller {
  @SuccessResponse('200', 'Returns Token')
  @Post('/login')
  public async login(
    @Body() body: TokenRequest,
    @Response() res: ExpressResponse
  ): Promise<TokenResponse> {
    // 执行登录逻辑,生成token和refreshToken
    const token = '生成的JWT Token';
    const refreshToken = '生成的Refresh Token';

    // 设置跨子域Cookie
    res.cookie('authToken', token, {
      domain: '.your-main-domain.com', // 主域名前加.,允许所有子域共享
      path: '/',
      httpOnly: true, // 禁止前端JS访问,防范XSS
      secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS
      sameSite: 'lax', // 根据业务需求选择strict/lax/none
      maxAge: 24 * 60 * 60 * 1000 // 有效期1天
    });

    res.cookie('refreshToken', refreshToken, {
      domain: '.your-main-domain.com',
      path: '/',
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: 7 * 24 * 60 * 60 * 1000 // 有效期7天
    });

    return { token };
  }
}

方式2:使用TSOA Controller基类的response属性

TSOA的Controller基类已封装Express的Response实例,直接通过this.response访问即可:

import { Controller, Route, Tags, Post, Body, SuccessResponse } from 'tsoa';
import { TokenRequest, TokenResponse } from './your-types-file';

@Route('auth')
@Tags('Auth')
export class AuthController extends Controller {
  @SuccessResponse('200', 'Returns Token')
  @Post('/login')
  public async login(@Body() body: TokenRequest): Promise<TokenResponse> {
    // 执行登录逻辑,生成token和refreshToken
    const token = '生成的JWT Token';
    const refreshToken = '生成的Refresh Token';

    // 使用this.response设置Cookie
    this.response.cookie('authToken', token, {
      domain: '.your-main-domain.com',
      path: '/',
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: 24 * 60 * 60 * 1000
    });

    this.response.cookie('refreshToken', refreshToken, {
      domain: '.your-main-domain.com',
      path: '/',
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: 7 * 24 * 60 * 60 * 1000
    });

    return { token };
  }
}

关键注意事项

  1. 启用cookie-parser中间件:在Express应用中添加app.use(cookieParser()),否则res.cookie方法无法正常工作。
  2. 前端请求配置:子域名的前端应用发送请求时,需设置withCredentials: true(Axios/Fetch均支持该配置),否则浏览器不会自动携带Cookie。
  3. 生产环境要求:
    • 必须使用HTTPS,否则secure: true的Cookie不会被浏览器保存;
    • 若需跨站点共享Cookie(SameSite=None),必须同时设置secure: true。
  4. Cookie参数说明:
    • domain:必须设置为主域(如.example.com),不能是具体子域,否则其他子域无法读取;
    • httpOnly:建议开启,避免Token被前端JS窃取,降低XSS风险;
    • sameSite:根据业务场景选择,lax是默认值,兼顾安全和可用性。

内容的提问来源于stack exchange,提问作者Haydn Morris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:55:54