如何基于AWS Cognito用户ID控制API Gateway端点访问权限
AWS 生态下实现商品创建者专属更新权限的最佳方案
基于你已经搭好的Cognito JWT授权器、API Gateway路由、商品创建端点的基础,整个实现不需要引入额外的复杂服务,按照分层校验的思路落地即可,具体实现路径和最佳实践如下:
核心实现流程
API Gateway层:仅完成登录合法性校验,透传可信用户身份
你当前配置的Cognito JWT授权器已经完成了JWT签名验证、有效期校验、受众匹配等基础登录校验工作,不需要再在授权器里叠加商品归属的校验逻辑。只需要在API Gateway的方法映射配置里,把授权器解析出的用户唯一标识(即Cognito的sub字段,对应用户在用户池内的永久唯一ID)透传到Lambda的请求上下文中,对应取值路径为requestContext.authorizer.claims.sub。
注意:不要在Lambda内部手动解析JWT获取用户身份,这种做法相当于跳过了API Gateway的授权校验,存在身份伪造的安全风险,直接读取授权器透传的字段即可。Lambda层:完成资源归属的二次校验(不可省略)
API Gateway无法感知业务数据库里存储的商品归属信息,这部分校验必须在Lambda内落地,有两种常用的实现方式:- 通用实现:从透传的上下文拿到当前请求的用户
sub,根据路径参数里的item-id查询对应商品的存储记录,对比记录里存储的creatorId(创建商品时写入的创建者sub)和当前用户ID,不匹配直接返回403权限错误,匹配后再执行后续的请求参数校验、数据更新逻辑。 - 性能优化实现:如果使用DynamoDB存储商品数据,可以直接把归属校验嵌入更新请求的条件表达式中,省去单独的商品读取操作:
当DynamoDB返回UpdateItem({ TableName: "你的商品表名", Key: { itemId: 路径参数传入的item-id }, ConditionExpression: 'creatorId = :currentUserId', UpdateExpression: 'SET title = :title, price = :price', ExpressionAttributeValues: { ':currentUserId': 透传的当前用户sub, ':title': 请求体传入的新标题, ':price': 请求体传入的新价格 } })ConditionalCheckFailedException时,直接捕获异常返回403即可,这种方式比先读再改的成本更低,还能避免并发场景下的权限绕过问题。
- 通用实现:从透传的上下文拿到当前请求的用户
配套最佳实践
- 商品的创建者归属必须存储Cognito的
sub字段,不要用用户邮箱、手机号这类可变字段做归属标识,避免用户修改账号信息后丢失商品所有权。 - 确认已落地的商品创建逻辑中,会把当前登录用户的
sub写入商品记录的creatorId字段,这是后续归属校验的基础;如果之前漏存,需要先补全历史商品的归属数据,避免出现老商品无法正常更新的问题。 - 所有身份判断必须基于API Gateway透传的授权器上下文,绝对不要信任请求体、查询参数里传入的用户ID字段,防止用户伪造请求篡改他人商品。
- 不要把资源归属校验放到自定义API Gateway授权器里实现:自定义授权器存在冷启动延迟、调用成本更高的问题,在Lambda层做归属校验的链路更短、维护成本更低。
- 权限逻辑预留扩展空间:后续如果需要支持平台管理员修改所有商品,只需要在Lambda的校验逻辑里增加管理员身份判断即可,不需要改动API Gateway的基础配置。
- 权限失败的响应要和参数错误、资源不存在的响应明确区分,方便后续通过访问日志做异常排查。
内容的提问来源于stack exchange,提问作者Tharanga
相关产品推荐
相关产品推荐

