调用API端点遇Forbidden错误:API密钥验证问题排查请求
API Gateway启用API密钥后调用返回Forbidden问题排查与修复
问题现象
无API密钥时可正常调用端点:
https://xxxxxxxx6.execute-api.us-east-1.amazonaws.com/test/pets
添加API密钥配置后,通过?key=abcdef查询参数调用时返回Forbidden错误。
相关资源配置
Lambda函数配置
MyLambdaFunction: Type: AWS::Serverless::Function Properties: Description: > Currently does not support S3 upload event. Handler: app.lambda_handler Runtime: python3.12 FunctionName: !Sub - "${TheEnv}-${TheAppNameForResources}-get-v1" - TheEnv: !Ref Environment TheAppNameForResources: !Ref AppNameForResources CodeUri: . MemorySize: 10240 Role: !GetAtt MyLambdaExecutionRole.Arn Events: MyPetsAPIEvent: Type: Api Properties: RestApiId: Ref: MyApiGateway Path: /pets Method: GET RequestParameters: - method.request.header.Authorization: Required: true Caching: true Tracing: Active
API Gateway配置
MyApiGateway: Type: AWS::Serverless::Api Properties: Variables: stageName: test Name: !Sub - '${TheEnv}-${TheAppNameForResources}-api' - TheEnv: !Ref Environment TheAppNameForResources: !Ref AppNameForResources TheBucketRegion: !Ref AWS::Region TracingEnabled: true OpenApiVersion: 3.0.2 Cors: AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" AllowMethods: "'*'" AllowOrigin: "'*'" StageName: test Auth: ApiKeyRequired: true UsagePlan: CreateUsagePlan: PER_API UsagePlanName: "my_api_batch" ResourcePolicy: CustomStatements: - Effect: Allow Principal: "*" Action: "execute-api:Invoke" Resource: "execute-api:/test/GET/pets"
IAM角色配置
MyLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub - "${TheAppNameForResources}-${TheEnvName}-lambda-execution-role" - TheAppNameForResources: !Ref AppNameForResources TheEnvName: !Ref Environment AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: ['sts:AssumeRole'] Policies: - PolicyName: !Sub - "${TheAppNameForResources}-${TheEnvName}-lambda-execution-role-policy" - TheAppNameForResources: !Ref AppNameForResources TheEnvName: !Ref Environment PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' - 'batch:SubmitJob' - 'batch:DescribeJobs' - 'batch:CancelJob' - 'apiGateway:Invoke' - 'S3:*' Resource: "*"
Lambda函数代码
def lambda_handler(event, context): print('event ====> ', event) print(event['resource']) api_key = event['queryStringParameters']['key'] print('api_key = ', api_key) route = event['resource'] jobQueue = "dev-myjobQueue-api" batch_client = boto3.client('batch') if route == '/pets': response = batch_client.submit_job( jobDefinition='pets-job-def', jobName='pets-job-name', jobQueue=jobQueue, ) return { 'statusCode': 200, 'body': json.dumps('AWS Batch job submitted successfully.') }
问题根源
- API密钥传递方式错误:API Gateway要求API密钥通过
X-Api-Key请求头传递,而非URL查询参数key,不符合要求的传递方式会触发验证失败。 - Authorization头强制要求冲突:Lambda的API事件配置中强制要求
Authorization头,但当前场景仅需API密钥验证,缺少该头会直接被拒绝。 - API密钥未关联使用计划:启用
ApiKeyRequired: true后,API密钥必须关联到对应的使用计划my_api_batch,否则网关会拒绝请求。 - 资源Policy格式错误:
Resource字段格式不符合AWS规范,正确格式应为ARN格式,而非execute-api:/test/GET/pets。
修复步骤
1. 修正API密钥传递方式
将API密钥放在X-Api-Key请求头中,示例curl请求:
curl -H "X-Api-Key: abcdef" https://xxxxxxxx6.execute-api.us-east-1.amazonaws.com/test/pets
2. 移除不必要的Authorization头要求
修改Lambda的Events配置,删除RequestParameters中的Authorization必填项:
MyLambdaFunction: # ... 其他配置保留 Events: MyPetsAPIEvent: Type: Api Properties: RestApiId: !Ref MyApiGateway Path: /pets Method: GET # 移除以下配置 # RequestParameters: # - method.request.header.Authorization: # Required: true # Caching: true
3. 关联API密钥到使用计划
- 控制台操作:在API Gateway控制台找到你的API密钥,将其关联到
my_api_batch使用计划。 - SAM模板添加资源(可选):
MyApiKey: Type: AWS::ApiGateway::ApiKey Properties: Name: "my-api-key" Enabled: true StageKeys: - RestApiId: !Ref MyApiGateway StageName: test MyUsagePlanKey: Type: AWS::ApiGateway::UsagePlanKey Properties: KeyId: !Ref MyApiKey KeyType: API_KEY UsagePlanId: !GetAtt MyApiGateway.UsagePlan.Id
4. 修正资源Policy格式
修改API Gateway的ResourcePolicy为正确的ARN格式:
MyApiGateway: # ... 其他配置保留 Auth: ApiKeyRequired: true UsagePlan: CreateUsagePlan: PER_API UsagePlanName: "my_api_batch" ResourcePolicy: CustomStatements: - Effect: Allow Principal: "*" Action: "execute-api:Invoke" Resource: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MyApiGateway}/test/GET/pets"
5. 调整Lambda代码(可选)
如果需要在Lambda中获取API密钥,从请求头而非查询参数读取:
def lambda_handler(event, context): print('event ====> ', event) print(event['resource']) # 从请求头获取API密钥 api_key = event.get('headers', {}).get('X-Api-Key') print('api_key = ', api_key) route = event['resource'] jobQueue = "dev-myjobQueue-api" batch_client = boto3.client('batch') if route == '/pets': response = batch_client.submit_job( jobDefinition='pets-job-def', jobName='pets-job-name', jobQueue=jobQueue, ) return { 'statusCode': 200, 'body': json.dumps('AWS Batch job submitted successfully.') }
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

