tRPC中Cookie处理困惑:服务端发送与客户端读取问题
问题核心
你的代码存在三个关键问题:
- CORS 未配置允许跨域携带凭证,导致 Cookie 无法在跨域场景下传递
- 客户端 tRPC 客户端未开启凭证携带,无法自动发送/接收 Cookie
- 服务端 Cookie 设置缺少必要的安全与跨域兼容参数
服务端代码修改
1. 修复 CORS 配置
跨域环境下必须明确允许凭证携带,同时指定可信的客户端 origin(不能用 *):
// backend/index.ts const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // 修改CORS配置 app.use(cors({ origin: "http://localhost:3000", // 替换为你的客户端实际地址 credentials: true, // 允许携带凭证(Cookie) })); app.use(cookieParser()) app.use( "/login/v1", trpcExpress.createExpressMiddleware({ router: loginRouter, createContext: createLoginContext }) ); app.listen(PORT, () => console.log(`server is running on port ${PORT}`));
2. 完善 Cookie 设置与返回值
给 Cookie 添加安全、跨域兼容参数,返回任意标识成功的内容即可(Cookie 通过响应头传递,不在返回体里):
// backend/router.ts export async function createLoginContext({req,res}: trpcExpress.CreateExpressContextOptions) { return { req, res } } export type LoginContext = trpc.inferAsyncReturnType<typeof createLoginContext> export const loginRouter = trpc.router<LoginContext>() .mutation('testCookies', { async resolve({ctx, input}):Promise<{ success: boolean; message: string }> { console.log('Received cookies:', ctx.req.cookies); // 设置Cookie并添加必要参数 ctx.res.cookie('testCookie', 'cooookkiiieee', { httpOnly: true, // 防止XSS攻击,禁止前端JS读取 secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS传输 sameSite: 'lax', // 兼容跨域场景,防止CSRF maxAge: 24 * 60 * 60 * 1000, // 有效期1天 path: '/' // 全站可访问 }); return { success: true, message: 'Cookie已设置' }; } });
客户端代码修改
1. 配置 tRPC 客户端携带凭证
开启 fetch 的凭证携带选项,让浏览器自动处理 Cookie 的发送与接收:
// client/requests.ts const createLoginRouter = () => { return createTRPCClient<LoginRouter>({ url: "http://localhost:5000/login/v1", // 自定义fetch逻辑,开启凭证携带 fetch: (input, init) => { return fetch(input, { ...init, credentials: 'include', // 关键:允许携带Cookie等凭证 }); }, }); };
2. 读取响应中的 Cookie
如果是浏览器环境,可直接用 document.cookie 或第三方库(如 universal-cookie)读取:
// client/requests.ts import Cookies from 'universal-cookie'; // 需先安装:npm i universal-cookie export const testCookiesRequest = async() => { const client = createLoginRouter(); const cookies = new Cookies(); try { const val = await client.mutation('testCookies'); // 读取刚设置的Cookie const testCookie = cookies.get('testCookie'); console.log('获取到的Cookie:', testCookie); return val; } catch(e) { throw e; } };
关键注意事项
- 客户端与服务端的 origin 必须匹配 CORS 配置中的
origin值,否则浏览器会拦截 Cookie - 生产环境必须开启
secure: true,否则 Cookie 不会在 HTTPS 下传输 httpOnly: true的 Cookie 无法通过前端 JS 读取,只能由浏览器自动在请求中携带,这是安全最佳实践
内容的提问来源于stack exchange,提问作者branperr
相关产品推荐
相关产品推荐

