在AWS Lambda+Apollo Server中设置多Set-Cookie头的问题求助
问题背景
基于AWS Lambda与API Gateway V2(HTTP API),使用@as-integrations/aws-lambda包开发Apollo Server的GraphQL API。用户登录流程中需要设置三个Cookie:idToken、accessToken、refreshToken。
问题现象
Lambda返回响应时,三个Cookie被合并到单个Set-Cookie头中,以逗号分隔。浏览器仅识别第一个Cookie(idToken),忽略其余两个,导致后续请求仅携带idToken,缺失accessToken和refreshToken。测试了fetch、axios、graphql-request等多种客户端库,问题一致,确认问题出在服务端。
响应头示例:
Set-Cookie: idToken=...; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=3600, accessToken=...; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=3600, refreshToken=...; Path=/; HttpOnly; Secure; SameSite; Max-Age=86400
服务端相关代码
Apollo Server Cookie插件代码
const cookiePlugin: ApolloServerPlugin = { async requestDidStart() { return { async willSendResponse( requestContext: GraphQLRequestContextWillSendResponse<any> ) { const { contextValue, response } = requestContext; const setCookies = contextValue.setCookies || []; if (setCookies.length > 0) { response.http.headers.set( "Set-Cookie", setCookies .map((cookie) => { const parts = [`${cookie.name}=${cookie.value}`]; parts.push(`Path=${cookie.options.path}`); if (cookie.options.httpOnly) { parts.push("HttpOnly"); } if (cookie.options.secure) { parts.push("Secure"); } parts.push(`SameSite=${cookie.options.sameSite}`); parts.push(`Max-Age=${cookie.options.maxAge}`); return parts.join("; "); }) .join(", ") ); } }, }; }, };
认证函数设置Cookie的代码
context.setCookies.push( { name: "idToken", value: IdToken, options: { ...cookieOptions, maxAge: 3600, }, }, { name: "accessToken", value: AccessToken, options: { ...cookieOptions, maxAge: 3600, }, }, { name: "refreshToken", value: RefreshToken, options: { ...cookieOptions, maxAge: 86400, }, } );
服务端配置代码
const publicServer = new ApolloServer({ typeDefs: publicTypeDefs, resolvers: publicResolvers, csrfPrevention: false, plugins: [cookiePlugin], }); export const graphqlHandler = startServerAndCreateLambdaHandler( publicServer, handlers.createAPIGatewayProxyEventV2RequestHandler(), { context: ctx, middleware: [ async (event) => { return async (result) => { result.headers = { ...result.headers, "access-control-allow-headers": "content-type, authorization, recaptcha", "access-control-allow-methods": "*", "access-control-allow-origin": origin, "access-control-allow-credentials": "true", }; return result; }; }, ], } );
已尝试的解决方案
- 将
response.http.headers['Set-Cookie']设置为Cookie字符串数组:Set-Cookie头完全消失 - 在Lambda响应中使用
multiValueHeaders:API Gateway V2(HTTP API)不支持该方式 - 调整中间件处理头信息:无法实现多个
Set-Cookie头单独发送
已知认知
- HTTP协议中,每个Cookie应单独使用一个
Set-Cookie头,合并到单个头会导致浏览器仅接受第一个Cookie - AWS API Gateway若处理不当,可能会合并同名的多个头
问题咨询
- 如何在AWS Lambda(搭配API Gateway与Apollo Server)的响应中正确设置多个
Set-Cookie头,让浏览器能识别所有Cookie? - 是否有办法让AWS API Gateway V2正确发送Lambda返回的多个
Set-Cookie头?是否需要调整响应头的设置方式?
补充信息
- 使用AWS API Gateway V2(HTTP API)
- 客户端
fetch请求包含credentials: 'include' - 问题在不同客户端HTTP库中均存在,确认问题出在服务端
内容的提问来源于stack exchange,提问作者Milad Jafari
相关产品推荐
相关产品推荐

