You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firestore权限拒绝问题求助:无法获取Vehicles集合数据

问题:Firestore获取车辆数据时触发PERMISSION_DENIED权限错误

开发Android应用时,调用Firestore读取Profiles/{userId}/Vehicles集合数据时,持续收到PERMISSION_DENIED: Missing or insufficient permissions错误,调整Firestore规则后问题仍未解决,目标是正常获取该用户下的所有车辆详情。

相关代码(vehicleList.kt)

@Suppress("DEPRECATION")
class VehiclesList : AppCompatActivity() {
    private val db = Firebase.firestore
    private lateinit var adapter: AdapterVehiclesList
    private var allVehicles: List<Vehicle> = ArrayList() // Store all vehicles from Firebase
    private lateinit var sharedPreferences: SharedPreferences
    private var userID:String = ""
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_vehicles_list)
        val rv:RecyclerView = findViewById(R.id.rvVehicleList)
        val layoutManager = LinearLayoutManager(this)

        sharedPreferences = getSharedPreferences("MyPrefs", MODE_PRIVATE)
        userID = sharedPreferences.getString("storedUserId", "userID").toString()

        FirebaseApp.initializeApp(this)
        val firebaseAppCheck = FirebaseAppCheck.getInstance()
        firebaseAppCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance())

        adapter = AdapterVehiclesList(ArrayList()) // Pass an empty list for now
        rv.layoutManager = layoutManager
        rv.adapter = adapter

        val searchView: EditText = findViewById(R.id.searchVehicle) // Replace with your SearchView ID
        searchView.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                filterData(s.toString().trim())
            }
            override fun afterTextChanged(s: Editable?) {}
        })
        fetchVehicleData(adapter)
    }

    private fun fetchVehicleData(adapter: AdapterVehiclesList) {
        val user = Firebase.auth.currentUser
        if (user != null) {
            val appCheck = Firebase.appCheck
            appCheck.getToken(true).addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    db.collection("Profiles").document(userID).collection("Vehicles")
                        .get()
                        .addOnSuccessListener { result ->
                            val vehicleList = ArrayList<Vehicle>()
                            for (document in result) {
                                val vehicleNumber = document.id
                                val driverName = document.getString("DriverName") ?: ""
                                val mobileNumber = document.getString("MobileNumber") ?: ""
                                val totalFilling = document.getDouble("TotalFilling") ?: 0.0

                                val vehicle =
                                    Vehicle(vehicleNumber, driverName, mobileNumber, totalFilling)
                                vehicleList.add(vehicle)
                            }
                            allVehicles = vehicleList // Store all vehicles
                            adapter.setData(vehicleList)
                        }
                        .addOnFailureListener { exception ->
                            Log.e("FetchData", "Error getting documents: ", exception)
                        }
                }
                else{
                    Toast.makeText(
                        this,
                        "Failed to Add vehicle\n Try Again...",
                        Toast.LENGTH_LONG
                    ).show()
                }
            }.addOnFailureListener{Exception->
                Log.e("AddVehicle", "Failed to Add vehicle2", Exception)
            }
        }
    }

当前Firestore规则

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /Profiles/{userId} {
      allow read, write: if
        request.auth != null &&
        request.auth.token.firebase.identities['firestore.googleapis.com'] != null &&
        request.auth.token.firebase.identities['firestore.googleapis.com'] != [] &&
        request.auth.token.appCheck.claims['https://firebaseappcheck.googleapis.com/claims'] != null &&
        request.auth.uid == userId;
    }
    match /Profiles/{userId}/Vehicles/{vehicleId} {
      allow read: if
        request.auth != null &&
        request.auth.token.firebase.identities['firestore.googleapis.com'] != null &&
        request.auth.token.firebase.identities['firestore.googleapis.com'] != [] &&
        request.auth.token.appCheck.claims['https://firebaseappcheck.googleapis.com/claims'] != null &&
        request.auth.uid == userId;
    }
    match /{document=**} {
      allow read, write: if
        request.auth != null &&
        request.auth.token.firebase.identities['firestore.googleapis.com'] != null &&
        request.auth.token.firebase.identities['firestore.googleapis.com'] != [] &&
        request.auth.token.appCheck.claims['https://firebaseappcheck.googleapis.com/claims'] != null;
    }
  }
}

错误信息

Error getting documents:                                                                     
com.google.firebase.firestore.FirebaseFirestoreException:
PERMISSION_DENIED: Missing or insufficient permissions.

解决方法

1. 修正Firestore规则中的App Check验证逻辑

当前规则中对App Check的校验写法错误,Firestore规则v2版本中,App Check验证应使用request.app != null,无需复杂的token解析。修改后的规则如下:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /Profiles/{userId} {
      allow read, write: if request.auth != null && request.app != null && request.auth.uid == userId;
    }
    match /Profiles/{userId}/Vehicles/{vehicleId} {
      allow read: if request.auth != null && request.app != null && request.auth.uid == userId;
    }
    match /{document=**} {
      allow read, write: if request.auth != null && request.app != null;
    }
  }
}

2. 验证userID与当前登录用户UID一致性

代码中userID来自SharedPreferences的storedUserId,需确保其与Firebase.auth.currentUser?.uid完全一致。可在fetchVehicleData中添加日志排查:

// 在fetchVehicleData方法内、user != null的判断后添加
Log.d("UserIDVerify", "Stored userID: $userID | Current auth UID: ${user.uid}")

若两者不一致,检查SharedPreferences存储逻辑,确保存储的是登录用户的真实UID。

3. 确认App Check配置正确性

  • 检查Firebase控制台是否已启用App Check,并为Android应用配置SafetyNet提供者;
  • 确认应用的SHA-256指纹已正确添加到Firebase控制台的App Check设置中;
  • 代码中App Check初始化位置正确(已在onCreate中完成),无需调整。

4. 分步调试规则定位问题

可临时简化规则,先移除App Check验证,仅保留用户身份校验:

match /Profiles/{userId}/Vehicles/{vehicleId} {
  allow read: if request.auth != null && request.auth.uid == userId;
}

若此时能正常获取数据,再逐步添加App Check验证,确认规则中哪部分导致权限失败。


内容的提问来源于stack exchange,提问作者Jaivik Kotadiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:39:55