API Gateway配置多源Access-Control-Allow-Origin报错,如何返回单值?
我有一个配置了CORS的Rest API,因无法使用通配符*,需指定允许访问应用的源列表。我创建了名为AllowedOrigins的参数,值为http://localhost:4200,http://somethingelse.com,并通过以下AWS Serverless资源配置CORS:
Resources: RestApi: Type: AWS::Serverless::Api Properties: StageName: Prod Cors: AllowOrigin: !Sub "'${AllowedOrigins}'" AllowHeaders: "'Content-Type'" AllowCredentials: true MaxAge: "'3600'"
OPTIONS方法返回了响应头,但出现如下错误:
Access to XMLHttpRequest at
'https://myApi.execute-api.eu-west-1.amazonaws.com/Prod/cars' from
origin 'null' has been blocked by CORS policy: Response to preflight
request doesn't pass access control check: The
'Access-Control-Allow-Origin' header contains multiple values
'http://localhost:4200,http://somethingelse.com', but only one is
allowed.
请问如何过滤Access-Control-Allow-Origin使其仅返回单个值?
AWS Serverless的Cors内置配置不支持动态匹配请求源并返回单一Origin,你需要通过以下方式解决:
方法一:用Lambda代理处理CORS请求
放弃Serverless Api资源的内置CORS配置,改用Lambda代理来处理OPTIONS预请求和实际请求的CORS头:
- 创建Lambda函数,逻辑如下:
- 读取请求头里的
Origin字段 - 校验该Origin是否在
AllowedOrigins列表中 - 匹配成功则返回包含
Access-Control-Allow-Origin: [匹配的Origin]的响应头,同时带上Access-Control-Allow-Credentials: true等必要头信息 - 匹配失败则返回403或不带允许头的响应
- 读取请求头里的
- 为API所有资源的OPTIONS方法配置Lambda代理集成,同时在实际请求的响应中也添加对应CORS头
方法二:借助API Gateway请求转换器或自定义授权器
通过API Gateway的扩展能力动态设置响应头:
- 请求转换器:读取请求的
Origin头,与允许列表匹配后,将匹配值注入到响应头的Access-Control-Allow-Origin字段 - 自定义授权器:在权限验证的同时,将匹配的Origin存入上下文变量,后续通过集成响应映射把该变量值设为
Access-Control-Allow-Origin头
关键注意点
- 直接在
AllowOrigin中传入多Origin的逗号分隔字符串不符合CORS规范,浏览器会直接拒绝这类响应 - 当开启
AllowCredentials: true时,Access-Control-Allow-Origin必须是单一的具体Origin,不能用通配符或多值列表
内容的提问来源于stack exchange,提问作者asfafafags

