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

如何为Cognito授权的LambdaRestApi(CDK)配置CORS跨域

问题原因

当你为LambdaRestApi设置defaultCorsPreflightOptions时,CDK会自动为所有API资源生成OPTIONS预检请求方法,而这个方法会默认继承defaultMethodOptions中的Cognito授权配置。但浏览器发送的预检请求不会携带身份凭证,将Cognito授权(包含authorizationScopes)应用到OPTIONS方法会触发API Gateway的校验错误——因为授权范围仅对携带有效用户池token的请求有意义,预检请求不满足这个条件。

解决方案

你需要让OPTIONS方法跳过授权校验,以下是三种可行的实现方式:

方式一:让Lambda处理CORS响应

直接在Lambda函数中返回CORS响应头,同时单独处理OPTIONS请求,无需依赖API Gateway自动生成预检方法:

Lambda代码示例(Node.js):

exports.handler = async (event) => {
  // 统一返回CORS头
  const corsHeaders = {
    "Access-Control-Allow-Origin": "*", // 可替换为指定域名
    "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type, Authorization"
  };

  // 处理预检请求,直接返回200
  if (event.httpMethod === 'OPTIONS') {
    return {
      statusCode: 200,
      headers: corsHeaders,
      body: ''
    };
  }

  // 业务逻辑处理
  const response = {
    statusCode: 200,
    headers: corsHeaders,
    body: JSON.stringify('处理结果')
  };
  return response;
};

CDK代码中移除defaultCorsPreflightOptions配置即可,所有请求(包括预检)都会代理到Lambda处理。

方式二:手动添加OPTIONS方法并禁用授权

手动为API资源创建OPTIONS方法,使用Mock集成直接返回CORS头,并明确设置授权类型为NONE:

CDK代码示例:

import { MockIntegration, PassthroughBehavior, AuthorizationType } from 'aws-cdk-lib/aws-apigateway';

const restApi = new LambdaRestApi(this, 'MyServiceRestApi', {
  handler: serviceAPIGWLambdaHandler,
  domainName: {
    domainName: `service.${rootDomain}`,
    certificate: Certificate.fromCertificateArn(
      this,
      `explanation`,
      serviceDomainCertificate.certificateArn,
    ),
  },
  proxy: true,
  endpointTypes: [EndpointType.EDGE],
  defaultMethodOptions: {
    authorizationType: AuthorizationType.COGNITO,
    authorizer,
    authorizationScopes: this.oauthScopes,
    methodResponses: [
      {
        statusCode: '200',
      },
    ],
  },
});

// 定义添加CORS预检方法的工具函数
const addCorsOptions = (resource: IResource) => {
  resource.addMethod('OPTIONS', new MockIntegration({
    integrationResponses: [{
      statusCode: '200',
      responseParameters: {
        'method.response.header.Access-Control-Allow-Origin': "'*'",
        'method.response.header.Access-Control-Allow-Methods': "'GET,POST,PUT,DELETE,OPTIONS'",
        'method.response.header.Access-Control-Allow-Headers': "'Content-Type,Authorization'",
      },
    }],
    passthroughBehavior: PassthroughBehavior.NEVER,
    requestTemplates: {
      'application/json': '{"statusCode": 200}',
    },
  }), {
    methodResponses: [{
      statusCode: '200',
      responseParameters: {
        'method.response.header.Access-Control-Allow-Origin': true,
        'method.response.header.Access-Control-Allow-Methods': true,
        'method.response.header.Access-Control-Allow-Headers': true,
      },
    }],
    // 关键:OPTIONS方法无需授权
    authorizationType: AuthorizationType.NONE,
  });
};

// 为根资源和代理资源添加OPTIONS方法
const rootResource = restApi.root;
const proxyResource = rootResource.getResource('{proxy+}')!;
addCorsOptions(rootResource);
addCorsOptions(proxyResource);

方式三:修改自动生成的OPTIONS方法配置

保留defaultCorsPreflightOptions,通过CDK的属性覆盖功能,修改自动生成的OPTIONS方法的授权配置:

CDK代码示例:

const restApi = new LambdaRestApi(this, 'MyServiceRestApi', {
  handler: serviceAPIGWLambdaHandler,
  domainName: {
    domainName: `service.${rootDomain}`,
    certificate: Certificate.fromCertificateArn(
      this,
      `explanation`,
      serviceDomainCertificate.certificateArn,
    ),
  },
  defaultCorsPreflightOptions: { allowOrigins: Cors.ALL_ORIGINS },
  proxy: true,
  endpointTypes: [EndpointType.EDGE],
  defaultMethodOptions: {
    authorizationType: AuthorizationType.COGNITO,
    authorizer,
    authorizationScopes: this.oauthScopes,
    methodResponses: [
      {
        statusCode: '200',
      },
    ],
  },
});

// 遍历所有资源,修改OPTIONS方法的授权配置
const updateOptionsMethods = (resource: IResource) => {
  const optionsMethod = resource.methods.find(m => m.httpMethod === 'OPTIONS');
  if (optionsMethod) {
    // 设置授权类型为NONE
    (optionsMethod as Method).addPropertyOverride('AuthorizationType', AuthorizationType.NONE);
    // 移除自动添加的授权器和范围配置
    optionsMethod.addPropertyDeletionOverride('AuthorizerId');
    optionsMethod.addPropertyDeletionOverride('AuthorizationScopes');
  }
  // 递归处理子资源
  resource.children.forEach(child => updateOptionsMethods(child as IResource));
};

updateOptionsMethods(restApi.root);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 15:26:00