Laravel本地传S3正常,EC2 Ubuntu Apache环境上传遇AccessDenied问题
Laravel EC2部署后S3上传AccessDenied问题排查方案
检查EC2实例的IAM角色权限
- 确认EC2绑定的IAM角色包含
s3:PutObject、s3:GetObject、s3:PutObjectAcl权限,资源要指定到目标Bucket(比如arn:aws:s3:::你的Bucket名/*) - 别在服务器硬编码本地的AWS凭证,EC2优先用IAM角色获取权限,避免凭证冲突
- 验证权限:在EC2上安装AWS CLI,执行
aws s3 cp test.txt s3://你的Bucket名/,能上传就排除权限本身问题
- 确认EC2绑定的IAM角色包含
核对Laravel的S3配置
- 检查
.env里的AWS_DEFAULT_REGION和Bucket所在区域完全一致,AWS_BUCKET名称没写错,AWS_USE_PATH_STYLE_ENDPOINT根据区域调整(多数区域设为false) - 上传代码里要明确指定ACL,比如
'visibility' => 'public'或者'ACL' => 'public-read',确保服务器端和本地逻辑一致 - 清理Laravel缓存:运行
php artisan config:clear和php artisan cache:clear,避免旧配置缓存捣乱
- 检查
复查S3 Bucket的权限设置
- 确认Bucket的公共访问设置里,所有阻止公共访问的选项都已关闭(包括阻止新公共ACL、阻止继承公共访问等)
- 检查Bucket策略是否允许EC2的IAM角色访问,示例策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::你的AWS账户ID:role/EC2绑定的IAM角色名" }, "Action": [ "s3:PutObject", "s3:GetObject", "s3:PutObjectAcl" ], "Resource": "arn:aws:s3:::你的Bucket名/*" } ] } - 确保Bucket的ACL设置了对应权限,上传的文件能继承公共访问权限
检查Apache/PHP运行环境
- 确认Apache运行用户(比如
www-data)能读取.env文件,文件权限设为644,所属组改成www-data - 验证AWS SDK依赖:执行
composer show aws/aws-sdk-php,没找到就运行composer install --no-dev(生产环境别装dev依赖) - 查看Laravel日志(
storage/logs/laravel.log),里面的错误信息比S3的XML提示更具体,比如凭证获取失败、区域不匹配等
- 确认Apache运行用户(比如
排查文件上传逻辑细节
- 确认上传的文件名没有特殊字符,避免S3路径解析出错
- 检查代码里有没有针对本地环境的特殊处理,比如本地用相对路径、服务器用绝对路径,导致上传逻辑不一致
内容的提问来源于stack exchange,提问作者Istiyak Sheyam
相关产品推荐
相关产品推荐

