在Amazon API Gateway中通过自定义授权器在URL传API Key遇权限问题
问题分析
你的核心问题是:自定义Lambda授权器执行成功,但API Gateway在使用计划验证阶段无法获取到API Key值,导致"Forbidden"错误。这是因为默认情况下,API Gateway不会自动将自定义授权器返回的usageIdentifierKey关联到API Key验证流程,需要手动补充验证逻辑或调整网关配置。
解决方法1:修改Lambda授权器,手动验证API Key与使用计划关联
步骤1:给Lambda执行角色添加权限
在IAM控制台中,为Lambda执行角色添加以下权限策略,允许查询API Key和使用计划的关联关系:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "apigateway:GetApiKey", "apigateway:GetUsagePlanKey" ], "Resource": [ "arn:aws:apigateway:us-east-1::/apikeys/*", "arn:aws:apigateway:us-east-1::/usageplans/*/keys/*" ] } ] }
步骤2:更新Lambda授权器代码
替换原有代码,加入API Key与使用计划的验证逻辑:
import { APIGatewayClient, GetApiKeyCommand, GetUsagePlanKeyCommand } from "@aws-sdk/client-apigateway"; const client = new APIGatewayClient({ region: "us-east-1" }); const TARGET_USAGE_PLAN_ID = "你的使用计划ID"; // 从AWS控制台获取使用计划ID const API_RESOURCE_ARN = "arn:aws:execute-api:us-east-1:xxxxxx:yyyyy/*/*/*/*"; // 保持原ARN export const handler = async (event) => { // 从查询参数中获取API Key const apiKey = event.queryStringParameters?.["x-api-key"]; if (!apiKey) { return generateDenyPolicy("anonymous"); } try { // 查询API Key详情 const apiKeyCmd = new GetApiKeyCommand({ apiKey, includeValue: false }); const apiKeyData = await client.send(apiKeyCmd); // 验证API Key是否关联目标使用计划 const usagePlanKeyCmd = new GetUsagePlanKeyCommand({ usagePlanId: TARGET_USAGE_PLAN_ID, keyId: apiKeyData.id }); await client.send(usagePlanKeyCmd); // 验证通过,返回允许策略 return { principalId: apiKey, usageIdentifierKey: apiKey, policyDocument: generateAllowPolicy() }; } catch (err) { // 验证失败,返回拒绝策略 return generateDenyPolicy("invalid-api-key"); } }; // 生成允许策略的辅助函数 const generateAllowPolicy = () => ({ Version: "2012-10-17", Statement: [{ Action: "execute-api:Invoke", Effect: "Allow", Resource: API_RESOURCE_ARN }] }); // 生成拒绝策略的辅助函数 const generateDenyPolicy = (principalId) => ({ principalId, policyDocument: { Version: "2012-10-17", Statement: [{ Action: "execute-api:Invoke", Effect: "Deny", Resource: API_RESOURCE_ARN }] } });
步骤3:重新部署并测试
- 重新部署Lambda函数,更新API Gateway的授权器配置,确保身份源设置为
querystring.x-api-key(注意格式,不是直接写x-api-key)。 - 使用
curl测试:curl "https://你的API ID.execute-api.us-east-1.amazonaws.com/你的阶段/路径?x-api-key=你的API Key值"
解决方法2:通过集成请求映射,直接将查询参数转为头部(无需自定义授权器)
如果不需要自定义授权器的额外逻辑,仅需支持URL传API Key,可直接通过网关配置实现:
- 进入API Gateway控制台,选择目标API的对应资源,打开集成请求设置。
- 在HTTP头部区域,点击添加头部,输入
x-api-key。 - 映射来自选择查询字符串,输入
x-api-key。 - 重新部署API到目标阶段,确保阶段已开启
API Key Required,且API Key已关联使用计划。 - 此时网关会自动将URL中的
x-api-key参数映射为请求头部,复用原有API Key验证逻辑。
关键排查点
- 确认阶段设置中
API Key Required已开启,且API Key与使用计划关联正确。 - 检查CloudWatch日志中Lambda的
event对象,确认queryStringParameters["x-api-key"]已正确获取到值。 - 验证Lambda执行角色的权限是否覆盖了API Key和使用计划的查询操作。
内容的提问来源于stack exchange,提问作者Noury
相关产品推荐
相关产品推荐

