Firebase存储权限错误:用户无权限访问对象的解决求助
问题描述
我开发了一款允许用户上传图片创建任务列表的应用,但点击「创建」按钮时会触发onFailureListener,提示**"User does not have permission to access this object"。当前仅配置了Firestore读写权限规则(仅登录用户可访问),但实际问题出在Firebase Storage权限上。尝试过相关规则后,又出现"Error in updating Profile"**错误。以下是我的代码和当前Firebase规则:
当前Firebase Firestore规则
// Allow read/write access on all documents to any user signed in to the application service cloud.firestore { match /databases/{database}/documents { match /{allPaths=**} { allow read, write: if request.auth != null; } } }
CreateBoardActivity.kt代码
package com.example.projectmanager.activities import android.Manifest import android.app.Activity import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.bumptech.glide.Glide import com.example.projectmanager.Firebase.FireStoreClass import com.example.projectmanager.R import com.example.projectmanager.models.Board import com.example.projectmanager.utils.Constants import com.google.firebase.storage.FirebaseStorage import com.google.firebase.storage.StorageReference import kotlinx.android.synthetic.main.activity_create_board.* import java.io.IOException class CreateBoardActivity : BaseActivity() { private var mSelectedImageFileUri : Uri? = null private lateinit var mUserName: String private var mBoardImageURL : String = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_create_board) setUpActionBar() if(intent.hasExtra(Constants.NAME)){ mUserName = intent.getStringExtra(Constants.NAME).toString() } iv_board_image.setOnClickListener{ if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){ Constants.showImageChooser(this) }else{ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), Constants.READ_STORAGE_PERMISSION_CODE) } } btn_create.setOnClickListener { if(mSelectedImageFileUri != null){ uploadBoardImage() } else{ showProgressDialog(resources.getString(R.string.please_wait)) createBoard() } } } private fun createBoard(){ val assignedUsersArrayList: ArrayList<String> = ArrayList() assignedUsersArrayList.add(getCurrentUserId()) val board = Board(et_board_name.text.toString(), mBoardImageURL, mUserName, assignedUsersArrayList) FireStoreClass().createBoard(this, board) } private fun uploadBoardImage(){ showProgressDialog(resources.getString(R.string.please_wait)) val sRef : StorageReference = FirebaseStorage.getInstance().reference.child( "BOARD_IMAGE" + System.currentTimeMillis() + "." + Constants.getFileExtension(this, mSelectedImageFileUri)) sRef.putFile(mSelectedImageFileUri!!).addOnSuccessListener { taskSnapshot-> Log.i("Board Image URL", taskSnapshot.metadata!!.reference!!.downloadUrl.toString()) taskSnapshot.metadata!!.reference!!.downloadUrl.addOnSuccessListener { uri-> Log.i("Downloadable Image URL", uri.toString()) mBoardImageURL = uri.toString() createBoard() } }.addOnFailureListener{ exception-> Toast.makeText(this, exception.message, Toast.LENGTH_LONG).show() hideProgressionDialog() } } fun boardCreatedSuccessfully(){ hideProgressionDialog() setResult(Activity.RESULT_OK) finish() } private fun setUpActionBar(){ setSupportActionBar(toolbar_create_board_activity) val actionBar = supportActionBar if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true) actionBar.setHomeAsUpIndicator(R.drawable.ic_black_color_white_24dp) actionBar.title = resources.getString(R.string.create_board_title) } toolbar_create_board_activity.setNavigationOnClickListener { onBackPressed() } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if(requestCode== Constants.READ_STORAGE_PERMISSION_CODE){ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){ } }else{ Toast.makeText(this, "You have denied the permission for storage. You can allow it from settings", Toast.LENGTH_LONG).show() } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if(resultCode == Activity.RESULT_OK && requestCode == Constants.PICK_IMAGE_REQUEST_CODE && data!!.data != null){ mSelectedImageFileUri = data.data try{ Glide.with(this) .load(mSelectedImageFileUri) .centerCrop() .placeholder(R.drawable.ic_board_place_holder) .into(iv_board_image) }catch(e: IOException){ e.printStackTrace() } } } }
解决方案
1. 配置正确的Firebase Storage规则
你当前仅配置了Firestore规则,但上传图片依赖Firebase Storage,需单独设置Storage权限规则。使用以下规则,确保仅登录用户可读写存储文件:
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if request.auth != null; } } }
规则说明
rules_version = '2':使用最新Storage规则版本match /b/{bucket}/o:匹配存储桶下所有对象allow read, write: if request.auth != null:仅允许已登录用户执行读写操作,与Firestore规则保持一致
2. 修复代码中废弃API问题
uploadBoardImage方法里的downloadUrl属性已被废弃,替换为getDownloadUrl()方法可避免潜在错误:
private fun uploadBoardImage(){ showProgressDialog(resources.getString(R.string.please_wait)) val sRef : StorageReference = FirebaseStorage.getInstance().reference.child( "BOARD_IMAGE" + System.currentTimeMillis() + "." + Constants.getFileExtension(this, mSelectedImageFileUri)) sRef.putFile(mSelectedImageFileUri!!).addOnSuccessListener { taskSnapshot-> // 使用getDownloadUrl()替代废弃的downloadUrl属性 sRef.getDownloadUrl().addOnSuccessListener { uri-> Log.i("Downloadable Image URL", uri.toString()) mBoardImageURL = uri.toString() createBoard() } }.addOnFailureListener{ exception-> Toast.makeText(this, exception.message, Toast.LENGTH_LONG).show() hideProgressionDialog() } }
3. 前置验证用户登录状态
在onCreate方法中添加登录状态检查,确保用户进入页面时已完成登录:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_create_board) // 检查用户是否已登录 if(FirebaseAuth.getInstance().currentUser == null){ startActivity(Intent(this, LoginActivity::class.java)) finish() return } setUpActionBar() // ... 其他原有代码 }
内容的提问来源于stack exchange,提问作者Aks K
相关产品推荐
相关产品推荐

