DRF部署AWS Lambda后上传文件报InvalidToken错误求助
排查AWS Lambda+Django DRF上传S3报InvalidToken错误的思路
1. 检查Django Settings中的AWS凭证配置问题
生产环境下Lambda会自动通过IAM角色注入临时凭证(AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN),如果你的settings.py中硬编码了这些值(尤其是AWS_SESSION_TOKEN),大概率会因为临时凭证过期或不匹配触发错误。
- 修正方案:确保生产环境的配置仅从环境变量读取,且不硬编码固定值:
# settings.py import os AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID', '') AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY', '') AWS_SESSION_TOKEN = os.environ.get('AWS_SESSION_TOKEN', '') AWS_STORAGE_BUCKET_NAME = 'your-production-bucket' AWS_S3_REGION_NAME = 'your-bucket-region' AWS_S3_SIGNATURE_VERSION = 's3v4' # 部分区域强制要求v4签名 DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
2. 排查Zappa配置的凭证覆盖问题
Zappa部署时如果在zappa_settings.json的生产环境配置中硬编码了aws_access_key_id和aws_secret_access_key,会覆盖Lambda的IAM角色凭证,导致使用错误的密钥/临时Token。
- 修正方案:删除生产环境配置中的这两个字段,让Zappa依赖部署权限执行,Lambda运行时使用指定的
execution_role:
// zappa_settings.json { "production": { "aws_region": "your-region", "django_settings": "your_project.settings", "execution_role": "arn:aws:iam::your-account-id:role/your-lambda-execution-role", // 移除 aws_access_key_id 和 aws_secret_access_key ... } }
3. 检查CI/CD脚本的环境变量传递问题
如果你的CI/CD脚本在部署时将开发环境的AWS凭证(包括临时AWS_SESSION_TOKEN)注入到Lambda的环境变量中,部署后这些Token会立即失效,引发错误。
- 修正方案:CI/CD脚本中仅保留部署所需的AWS凭证(用于Zappa打包上传),不要将这些凭证作为环境变量传递给Lambda运行时。例如,避免执行类似:
# 错误示例:不要将凭证传入Lambda环境 zappa update production --environment AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN
4. 验证S3区域与签名版本匹配
如果你的S3桶区域和settings.py中AWS_S3_REGION_NAME配置不一致,或者未指定正确的签名版本(如部分区域要求s3v4),会导致凭证验证失败。
- 修正方案:
- 确认S3桶的实际区域(在AWS控制台查看)
- 确保
AWS_S3_REGION_NAME与桶区域完全一致 - 添加
AWS_S3_SIGNATURE_VERSION = 's3v4'到settings中
5. 确认Lambda执行角色的权限与信任关系
再次验证:
- 角色拥有
s3:PutObject权限,且资源范围包含目标桶(如arn:aws:s3:::your-bucket/*) - 角色的信任关系允许
lambda.amazonaws.com作为信任实体(确保Lambda可以 AssumeRole 获取临时凭证)
6. 临时调试验证凭证有效性
在生产环境的视图中临时添加调试代码(测试后移除),打印Lambda注入的凭证信息,确认是否存在有效临时Token:
# 在上传视图中添加 import os print(f"AWS_ACCESS_KEY_ID: {os.environ.get('AWS_ACCESS_KEY_ID')}") print(f"AWS_SESSION_TOKEN exists: {bool(os.environ.get('AWS_SESSION_TOKEN'))}")
查看Lambda CloudWatch日志,如果AWS_SESSION_TOKEN为空或显示为开发环境的旧值,说明配置中存在硬编码或环境变量覆盖的问题。
内容的提问来源于stack exchange,提问作者Lorenzo
相关产品推荐
相关产品推荐

