本地SAM调用OPTIONS请求返回403且提示缺少认证令牌排查
OPTIONS请求返回403 "Missing Authentication Token" 问题排查与解决
问题原因
你的SAM模板同时采用了两种API定义方式:通过scanRecords函数的Events字段自动生成POST接口,又手动创建了scanRecordsResource、POST方法和OPTIONS方法。这种重复定义会导致SAM Local启动时,优先使用自动生成的API配置,而手动定义的OPTIONS方法未被正确加载到本地运行的API Gateway中。当OPTIONS请求到达时,API Gateway找不到匹配的无认证OPTIONS方法,反而可能匹配到需要Cognito认证的POST路由规则,从而返回403错误。
解决方案
方案1:用SAM Serverless::Api统一管理API(推荐)
SAM提供了更简洁的方式定义API和CORS,无需手动创建OPTIONS方法,修改模板如下:
- 添加Serverless::Api资源,配置CORS和认证:
"MyApi": { "Type": "AWS::Serverless::Api", "Properties": { "StageName": "dev", "Cors": { "AllowMethods": "'POST,OPTIONS'", "AllowHeaders": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", "AllowOrigin": "'*'" }, "Auth": { "DefaultAuthorizer": "CognitoAuthorizer", "Authorizers": { "CognitoAuthorizer": { "UserPoolArn": { "Ref": "YourCognitoUserPoolArn" } } } } } }
- 修改
scanRecords函数的Events,关联到上面的API:
"scanRecords": { "Type": "AWS::Serverless::Function", "Properties": { "Handler": "dist/dynamo/CRUD.scanRecords", "CodeUri": "./backend", "Policies": [ "AmazonDynamoDBFullAccess", "CloudWatchLogsFullAccess" ], "Events": { "PostScanRecords": { "Type": "Api", "Properties": { "Path": "/scanRecords", "Method": "post", "RestApiId": { "Ref": "MyApi" } } } } } }
- 删除手动定义的
scanRecordsResource、scanRecordsGatewayMethod、scanRecordsOptionsMethod,避免路由冲突。
SAM会自动为/scanRecords生成OPTIONS方法,配置正确的CORS头且无需认证。
方案2:修复手动定义的OPTIONS方法关联
如果坚持手动定义API资源,需做以下调整:
- 删除
scanRecords函数Events中的POST方法定义,避免重复路由。 - 确认
scanRecordsOptionsMethod的ResourceId和RestApiId正确关联到scanRecordsResource和apiGatewayRestApi。 - 启动SAM时加上
--debug参数,查看日志确认OPTIONS方法是否被加载:
sam local start-api --template lambdas_sam.json --debug
如果日志中没有OPTIONS方法的注册记录,说明模板定义存在语法或关联错误。
测试验证
修改后重新启动SAM本地服务,再次执行curl命令:
curl -i -X OPTIONS http://127.0.0.1:3000/scanRecords -H "Origin: http://localhost:4000" -H "Access-Control-Request-Method: POST"
应该返回200状态码及正确的CORS响应头。
内容的提问来源于stack exchange,提问作者Rilcon42
相关产品推荐
相关产品推荐

