Firebase Storage(Kotlin)获取downloadUrl时出现403权限错误
核心问题
Android Kotlin项目中,图片可正常上传至Firebase Storage,但调用downloadUrl时触发403权限错误,日志提示用户未登录(无法获取令牌)。
错误日志
- 令牌获取失败日志:
E/StorageUtil: error getting token java.util.concurrent.ExecutionException: com.google.firebase.internal.api.FirebaseNoSignedInUserException: Please sign in before trying to get a token.
- Storage权限错误日志:
E/StorageException: StorageException has occurred.
The user does not have permission to access this object.
Code: -13021 HttpResult: 403
E/StorageException: { "error": { "code": 403, "message": "Permission denied." }}
java.io.IOException: { "error": { "code": 403, "message": "Permission denied." }}
触发错误的代码片段
val urlTask = uploadTask?.continueWithTask { task -> if (!task.isSuccessful) { Toast.makeText(context, "Upload to Cloud Failed!", Toast.LENGTH_SHORT).show() task.exception?.let { throw it } } imagesRef?.downloadUrl // 错误触发位置 }
背景信息
- 问题始于开启邮箱/密码授权并关闭匿名登录后,虽已重新开启匿名登录
- 上传前已确认
Firebase.auth.currentUser不为空,图片上传功能正常 - 当前Firebase Storage规则:
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { allow write: if request.auth != null; allow read: if request.auth != null; } } }
解决步骤
确认获取downloadUrl时Auth令牌有效
上传成功后,currentUser存在不代表令牌已刷新完成。建议先强制刷新令牌,再获取downloadUrl:Firebase.auth.currentUser?.getIdToken(true) ?.addOnCompleteListener { tokenTask -> if (tokenTask.isSuccessful) { imagesRef?.downloadUrl?.addOnSuccessListener { uri -> // 处理获取到的下载链接 } } else { // 处理令牌刷新失败逻辑 } }指定任务执行线程,保证Auth上下文同步
默认continueWithTask可能在后台线程执行,导致Auth令牌未同步。改用主线程执行任务:val urlTask = uploadTask?.continueWithTask(TaskExecutors.MAIN_THREAD) { task -> if (!task.isSuccessful) { Toast.makeText(context, "Upload to Cloud Failed!", Toast.LENGTH_SHORT).show() task.exception?.let { throw it } } // 重新获取当前用户,确保上下文有效 if (Firebase.auth.currentUser == null) throw IllegalStateException("User session lost") imagesRef?.downloadUrl }排查验证:临时放宽Storage规则
暂时修改Storage规则为:rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { allow write: if request.auth != null; allow read: if true; } } }若此时能正常获取downloadUrl,说明问题出在Auth令牌传递环节,回到前两步修复即可。
检查Firebase初始化时机
确保在Application类中完成Firebase初始化,避免在Activity早期生命周期调用Auth/Storage操作,导致令牌未加载完成。
内容的提问来源于stack exchange,提问作者stroopwafel

