从浏览器访问Firebase Storage签名URL提示“Access denied”
刚遇到过类似的问题,给你梳理几个最常见的排查方向,应该能解决你的AccessDenied错误:
先检查签名URL的完整性:你贴出来的URL只带了
GoogleAccessId参数,却缺少了Expires(过期时间戳)和signature(加密签名串)这两个核心参数!完整的签名URL必须同时包含这三个部分,格式大概是这样的:https://storage.googleapis.com/mango-b715d.appspot.com/thumb_ESP_014033_1910_desktop.jpg?GoogleAccessId=firebase-adminsdk-lar4y@mango-b715d.iam.gserviceaccount.com&Expires=1699999999&signature=abcdefghijklmnopqrstuvwxyz...你得回头看Cloud Function里生成签名URL的代码,是不是漏了参数生成逻辑?比如用Node.js的
@google-cloud/storage库的话,正确的写法应该是这样的:const { Storage } = require('@google-cloud/storage'); const storage = new Storage(); const bucket = storage.bucket('mango-b715d.appspot.com'); const targetFile = bucket.file('thumb_ESP_014033_1910_desktop.jpg'); // 生成V4版本的签名URL,设置1小时有效期 const [signedUrl] = await targetFile.getSignedUrl({ version: 'v4', action: 'read', expires: Date.now() + 3600 * 1000, // 1小时后过期 }); console.log('生成的签名URL:', signedUrl); // 打印出来确认参数是否完整要是代码里没正确调用
getSignedUrl或者配置错了参数,就会生成不完整的URL,自然访问被拒。确认服务账号的权限:用来生成签名的这个服务账号(
firebase-adminsdk-lar4y@mango-b715d.iam.gserviceaccount.com)必须拥有读取存储桶对象的权限。你可以去Google Cloud Console的IAM页面,找到这个账号,检查它的角色是不是包含Storage Object Viewer,或者自定义角色里有没有storage.objects.get这个权限。如果权限不够,就算URL生成对了,也会被拒绝访问。检查对象的ACL设置:虽然签名URL是通过服务账号授权的,但有时候对象本身的ACL可能限制了访问。你可以去Firebase Console的Storage页面,找到这张图片,查看它的权限配置,确保服务账号或者对应的主体有读取权限。不过这个概率相对低一些,先优先排查前面两点。
确认签名版本:尽量使用V4版本的签名(就是上面代码里的
version: 'v4'),V2版本的签名现在兼容性不如V4,容易出现权限验证失败的问题。
先按这几步排查,尤其是第一点,你现在的URL明显参数不全,大概率是生成的时候出了问题。
内容的提问来源于stack exchange,提问作者peppylearner

