FirebaseFirestoreException:PERMISSION_DENIED:权限缺失或不足
FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions
我的应用程序无法从 firebase firestore 读取时遇到问题。
我们有一个应用程序有 2 个变体发布和调试。它工作正常,我没有改变任何东西。
production/release 工作正常。
我正在开发一个单独的应用程序,该应用程序使用相同的 firestore,并且该应用程序也运行良好(尚未发布)。
我用谷歌搜索了这个问题,其中大部分都将我带到了这里,但几乎所有的答案都是将安全规则更改为:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
这是不安全的。我们的规则设置为:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow write: if request.auth != null;
}
}
}
FBAuthUI.kt
class FBAuthUI : AppCompatActivity() {
private val COLLECTION_PATH_USERS = "Users"
private val RC_SIGN_IN: Int = 100
private val RC_SIGN_UP: Int = 200
private val TAG = "AuthUiActivity"
private val TOS_URL = ""
private val PRIVACY_POLICY_URL = ""
// Choose authentication providers
private val providers = arrayListOf(
AuthUI.IdpConfig.EmailBuilder().build(),
AuthUI.IdpConfig.GoogleBuilder().build(),
AuthUI.IdpConfig.FacebookBuilder().build())
private var userRef: CollectionReference? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create and launch sign-in intent
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.setLogo(R.drawable.logo_red)
.setTheme(R.style.SignInTheme)
.setTosAndPrivacyPolicyUrls(
TOS_URL,
PRIVACY_POLICY_URL)
.build(),
RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.i(TAG, requestCode.toString())
if (requestCode == RC_SIGN_IN) {
val idpResponse = IdpResponse.fromResultIntent(data)
if (resultCode == Activity.RESULT_OK) {
try {
if (idpResponse?.isNewUser() == true) {
//signup code
…
} else {
startActivity(Intent(this, MainActivity::class.java))
}
} catch (e: JSONException) {
e.printStackTrace()
}
}else {
// Sign in failed. If response is null the user canceled the
// sign-in flow using the back button. Otherwise check
// response.getError().getErrorCode() and handle the error.
if (idpResponse != null) {
Log.d(TAG, idpResponse.error?.errorCode.toString())
Toast.makeText(this, "Unable to sign in. Please try again later", Toast.LENGTH_LONG).show()
} else {
startActivity(Intent(this, LandingPageActivity::class.java))
}
}
}
}
MainActivity.kt
class MainActivity : AppCompatActivity(),{
…
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val homeFrag: Fragment = Home()
val searchFrag: Fragment = SearchFragment()
val profileFrag: Fragment = ProfileFragment()
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_navigation)
bottomNav.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.home_nav -> {
commitFragment(homeFrag)
}
R.id.nav_search -> {
commitFragment(searchFrag)
}
R.id.profile_nav -> {
commitFragment(profileFrag)
}
else -> {
commitFragment(homeFrag)
}
}
true
}
if (savedInstanceState == null) {
bottomNav.selectedItemId = R.id.home_nav
}
setSupportActionBar(toolbar)
supportActionBar!!.setDisplayShowTitleEnabled(false)
}
private fun commitFragment(fragment: Fragment) {
val fm = supportFragmentManager
val fragTransition = fm.beginTransaction().addToBackStack(fragment.toString())
fragTransition.replace(R.id.container, fragment).commit()
}
companion object {
var bottomNav: BottomNavigationView? = null
var CONTEXT: Context? = null
private val TAG = MainActivity::class.java.simpleName
}
}
SearchFragment.java
public class SearchFragment extends Fragment {
private static final String COLLECTION_PATH_VENDORS = “BookStores”;
private SearchAdapter searchAdapter;
private ArrayList<BookStore> bookstores;
private String searchString;
private ImageView searchImage;
private EditText searchET;
Boolean clickedCategories;
ArrayList<BookStore> bkstore = new ArrayList<>();
ArrayList<String> list = new ArrayList<>();
private RecyclerView recyclerView;
private DatabaseReference dbRef;
private CollectionReference bookStoreRef;
private String category;
@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Initialize view
View fragmentView = inflater.inflate(R.layout.fragment_search, container, false);
recyclerView = fragmentView.findViewById(R.id.sr_recycler);
recyclerView.hasFixedSize();
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL));
// Obtain Cloud Firestore instance
FirebaseFirestore db = FirebaseFirestore.getInstance();
bookStoreRef = db.collection(COLLECTION_PATH_VENDORS);
searchET = getActivity().findViewById(R.id.search_box);
searchET.setCursorVisible(true);
displayAll();
SearchAdapter searchAdapter = new SearchAdapter(getContext(), bkstore);
recyclerView.setAdapter(searchAdapter);
return fragmentView;
}
private void displayAll() {
Log.d("UserID Tag ", FirebaseAuth.getInstance().getCurrentUser().getUid());
bookStoreRef.get().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
final BookStore aBookStore = new Bookstore();
aBookStore.setName(document.getString("Name"));
aBookStore.setCategory(document.getString("Category"));
aBookStore.setDescription(document.getString("Description"));
aBookStorek.setImage(document.getString("Image"));
aBookStore.setID(document.getId());
bkstore.add(DisplayResults(document));
recyclerView.removeAllViews();
}
} else {
Log.w(TAG, "Error getting documents.", task.getException());
}
});
}
private BookStore DisplayResults(QueryDocumentSnapshot document){
BookStore aBookStore = new BookStore();
aBookStore.setName(document.getString("Name"));
aBookStore.setCategory(document.getString("Category"));
aBookStore.setDescription(document.getString("Description"));
aBookStorek.setImage(document.getString("Image"));
aBookStore.setID(document.getId());
return aBookStore.;
}
}
日志returns:
D/UserID Tag: E4ARmAfe7aVG8oRiizHqWJatZlY2
W/Firestore: (24.0.0) [Firestore]: Listen for Query(target=Query(BookStores order by __name__);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
W/ContentValues: Error getting documents.
com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:117)
at com.google.firebase.firestore.core.EventManager.onError(EventManager.java:166)
at com.google.firebase.firestore.core.SyncEngine.removeAndCleanupTarget(SyncEngine.java:588)
at com.google.firebase.firestore.core.SyncEngine.handleRejectedListen(SyncEngine.java:424)
at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedListen(MemoryComponentProvider.java:104)
at com.google.firebase.firestore.remote.RemoteStore.processTargetError(RemoteStore.java:577)
at com.google.firebase.firestore.remote.RemoteStore.handleWatchChange(RemoteStore.java:461)
at com.google.firebase.firestore.remote.RemoteStore.access0(RemoteStore.java:53)
at com.google.firebase.firestore.remote.RemoteStore.onWatchChange(RemoteStore.java:176)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:109)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:38)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onNext$com-google-firebase-firestore-remote-AbstractStream$StreamObserver(AbstractStream.java:119)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$ExternalSyntheticLambda3.run(Unknown Source:4)
at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onNext(AbstractStream.java:110)
at com.google.firebase.firestore.remote.FirestoreChannel.onMessage(FirestoreChannel.java:131)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInternal(ClientCallImpl.java:656)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInContext(ClientCallImpl.java:641)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:234)
at java.lang.Thread.run(Thread.java:923)
Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions.
at io.grpc.Status.asException(Status.java:543)
at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:115)
at com.google.firebase.firestore.core.EventManager.onError(EventManager.java:166)
at com.google.firebase.firestore.core.SyncEngine.removeAndCleanupTarget(SyncEngine.java:588)
at com.google.firebase.firestore.core.SyncEngine.handleRejectedListen(SyncEngine.java:424)
at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedListen(MemoryComponentProvider.java:104)
at com.google.firebase.firestore.remote.RemoteStore.processTargetError(RemoteStore.java:577)
at com.google.firebase.firestore.remote.RemoteStore.handleWatchChange(RemoteStore.java:461)
at com.google.firebase.firestore.remote.RemoteStore.access0(RemoteStore.java:53)
at com.google.firebase.firestore.remote.RemoteStore.onWatchChange(RemoteStore.java:176)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:109)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:38)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onNext$com-google-firebase-firestore-remote-AbstractStream$StreamObserver(AbstractStream.java:119)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$ExternalSyntheticLambda3.run(Unknown Source:4)
at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onNext(AbstractStream.java:110)
at com.google.firebase.firestore.remote.FirestoreChannel.onMessage(FirestoreChannel.java:131)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInternal(ClientCallImpl.java:656)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInContext(ClientCallImpl.java:641)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:234)
at java.lang.Thread.run(Thread.java:923)
V/FA: Inactivity, disconnecting from the service
W/Firestore: (24.0.0) [WatchStream]: (9a4fb5d) Stream closed with status: Status{code=CANCELLED, description=Disconnecting idle stream. Timed out waiting for new targets., cause=null}.
我不知道问题出在哪里。我什至尝试更改安全规则,但仍然出现缺少权限的错误。
还有其他建议吗?
Firestore security rules
打开 Firebase 控制台,然后单击您的项目。
单击屏幕左侧的 Firestore。
在 Firestore 页面上,单击“规则”选项卡。
用以下规则替换现有规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /customers/{customerID} {
allow read:
if request.auth.uid != null
&& request.auth.token.firebase.sign_in_provider == "google.com"
&& request.auth.token.email == customerID
}
}
}
此规则授予客户集合的只读权限。该规则验证您是否已通过您在 Identity Platform 中配置的 Google 登录提供程序登录。它还确保您只能检索客户 ID 与您的电子邮件地址匹配的文档。
注意:无论请求是检索单个文档还是执行查询,对 Firestore 的请求始终根据数据库安全规则进行评估。
- 点击发布。
这里有两个单独的子句:
allow read;
allow write: if request.auth != null;
对于write
你要求用户进行身份验证,但是对于阅读你没有指定条件,这显然意味着不允许阅读。
我的猜测是您希望 if
子句应用于读取和写入,您可以这样做:
allow read, write: if request.auth != null;
我不确定根本问题是什么,但删除 google-services.json 并重新下载后,问题似乎已解决。
我的应用程序无法从 firebase firestore 读取时遇到问题。 我们有一个应用程序有 2 个变体发布和调试。它工作正常,我没有改变任何东西。
production/release 工作正常。
我正在开发一个单独的应用程序,该应用程序使用相同的 firestore,并且该应用程序也运行良好(尚未发布)。
我用谷歌搜索了这个问题,其中大部分都将我带到了这里,但几乎所有的答案都是将安全规则更改为:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
这是不安全的。我们的规则设置为:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow write: if request.auth != null;
}
}
}
FBAuthUI.kt
class FBAuthUI : AppCompatActivity() {
private val COLLECTION_PATH_USERS = "Users"
private val RC_SIGN_IN: Int = 100
private val RC_SIGN_UP: Int = 200
private val TAG = "AuthUiActivity"
private val TOS_URL = ""
private val PRIVACY_POLICY_URL = ""
// Choose authentication providers
private val providers = arrayListOf(
AuthUI.IdpConfig.EmailBuilder().build(),
AuthUI.IdpConfig.GoogleBuilder().build(),
AuthUI.IdpConfig.FacebookBuilder().build())
private var userRef: CollectionReference? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create and launch sign-in intent
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.setLogo(R.drawable.logo_red)
.setTheme(R.style.SignInTheme)
.setTosAndPrivacyPolicyUrls(
TOS_URL,
PRIVACY_POLICY_URL)
.build(),
RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.i(TAG, requestCode.toString())
if (requestCode == RC_SIGN_IN) {
val idpResponse = IdpResponse.fromResultIntent(data)
if (resultCode == Activity.RESULT_OK) {
try {
if (idpResponse?.isNewUser() == true) {
//signup code
…
} else {
startActivity(Intent(this, MainActivity::class.java))
}
} catch (e: JSONException) {
e.printStackTrace()
}
}else {
// Sign in failed. If response is null the user canceled the
// sign-in flow using the back button. Otherwise check
// response.getError().getErrorCode() and handle the error.
if (idpResponse != null) {
Log.d(TAG, idpResponse.error?.errorCode.toString())
Toast.makeText(this, "Unable to sign in. Please try again later", Toast.LENGTH_LONG).show()
} else {
startActivity(Intent(this, LandingPageActivity::class.java))
}
}
}
}
MainActivity.kt
class MainActivity : AppCompatActivity(),{
…
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val homeFrag: Fragment = Home()
val searchFrag: Fragment = SearchFragment()
val profileFrag: Fragment = ProfileFragment()
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_navigation)
bottomNav.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.home_nav -> {
commitFragment(homeFrag)
}
R.id.nav_search -> {
commitFragment(searchFrag)
}
R.id.profile_nav -> {
commitFragment(profileFrag)
}
else -> {
commitFragment(homeFrag)
}
}
true
}
if (savedInstanceState == null) {
bottomNav.selectedItemId = R.id.home_nav
}
setSupportActionBar(toolbar)
supportActionBar!!.setDisplayShowTitleEnabled(false)
}
private fun commitFragment(fragment: Fragment) {
val fm = supportFragmentManager
val fragTransition = fm.beginTransaction().addToBackStack(fragment.toString())
fragTransition.replace(R.id.container, fragment).commit()
}
companion object {
var bottomNav: BottomNavigationView? = null
var CONTEXT: Context? = null
private val TAG = MainActivity::class.java.simpleName
}
}
SearchFragment.java
public class SearchFragment extends Fragment {
private static final String COLLECTION_PATH_VENDORS = “BookStores”;
private SearchAdapter searchAdapter;
private ArrayList<BookStore> bookstores;
private String searchString;
private ImageView searchImage;
private EditText searchET;
Boolean clickedCategories;
ArrayList<BookStore> bkstore = new ArrayList<>();
ArrayList<String> list = new ArrayList<>();
private RecyclerView recyclerView;
private DatabaseReference dbRef;
private CollectionReference bookStoreRef;
private String category;
@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Initialize view
View fragmentView = inflater.inflate(R.layout.fragment_search, container, false);
recyclerView = fragmentView.findViewById(R.id.sr_recycler);
recyclerView.hasFixedSize();
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(),
DividerItemDecoration.VERTICAL));
// Obtain Cloud Firestore instance
FirebaseFirestore db = FirebaseFirestore.getInstance();
bookStoreRef = db.collection(COLLECTION_PATH_VENDORS);
searchET = getActivity().findViewById(R.id.search_box);
searchET.setCursorVisible(true);
displayAll();
SearchAdapter searchAdapter = new SearchAdapter(getContext(), bkstore);
recyclerView.setAdapter(searchAdapter);
return fragmentView;
}
private void displayAll() {
Log.d("UserID Tag ", FirebaseAuth.getInstance().getCurrentUser().getUid());
bookStoreRef.get().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
final BookStore aBookStore = new Bookstore();
aBookStore.setName(document.getString("Name"));
aBookStore.setCategory(document.getString("Category"));
aBookStore.setDescription(document.getString("Description"));
aBookStorek.setImage(document.getString("Image"));
aBookStore.setID(document.getId());
bkstore.add(DisplayResults(document));
recyclerView.removeAllViews();
}
} else {
Log.w(TAG, "Error getting documents.", task.getException());
}
});
}
private BookStore DisplayResults(QueryDocumentSnapshot document){
BookStore aBookStore = new BookStore();
aBookStore.setName(document.getString("Name"));
aBookStore.setCategory(document.getString("Category"));
aBookStore.setDescription(document.getString("Description"));
aBookStorek.setImage(document.getString("Image"));
aBookStore.setID(document.getId());
return aBookStore.;
}
}
日志returns:
D/UserID Tag: E4ARmAfe7aVG8oRiizHqWJatZlY2
W/Firestore: (24.0.0) [Firestore]: Listen for Query(target=Query(BookStores order by __name__);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
W/ContentValues: Error getting documents.
com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:117)
at com.google.firebase.firestore.core.EventManager.onError(EventManager.java:166)
at com.google.firebase.firestore.core.SyncEngine.removeAndCleanupTarget(SyncEngine.java:588)
at com.google.firebase.firestore.core.SyncEngine.handleRejectedListen(SyncEngine.java:424)
at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedListen(MemoryComponentProvider.java:104)
at com.google.firebase.firestore.remote.RemoteStore.processTargetError(RemoteStore.java:577)
at com.google.firebase.firestore.remote.RemoteStore.handleWatchChange(RemoteStore.java:461)
at com.google.firebase.firestore.remote.RemoteStore.access0(RemoteStore.java:53)
at com.google.firebase.firestore.remote.RemoteStore.onWatchChange(RemoteStore.java:176)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:109)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:38)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onNext$com-google-firebase-firestore-remote-AbstractStream$StreamObserver(AbstractStream.java:119)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$ExternalSyntheticLambda3.run(Unknown Source:4)
at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onNext(AbstractStream.java:110)
at com.google.firebase.firestore.remote.FirestoreChannel.onMessage(FirestoreChannel.java:131)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInternal(ClientCallImpl.java:656)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInContext(ClientCallImpl.java:641)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:234)
at java.lang.Thread.run(Thread.java:923)
Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions.
at io.grpc.Status.asException(Status.java:543)
at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:115)
at com.google.firebase.firestore.core.EventManager.onError(EventManager.java:166)
at com.google.firebase.firestore.core.SyncEngine.removeAndCleanupTarget(SyncEngine.java:588)
at com.google.firebase.firestore.core.SyncEngine.handleRejectedListen(SyncEngine.java:424)
at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedListen(MemoryComponentProvider.java:104)
at com.google.firebase.firestore.remote.RemoteStore.processTargetError(RemoteStore.java:577)
at com.google.firebase.firestore.remote.RemoteStore.handleWatchChange(RemoteStore.java:461)
at com.google.firebase.firestore.remote.RemoteStore.access0(RemoteStore.java:53)
at com.google.firebase.firestore.remote.RemoteStore.onWatchChange(RemoteStore.java:176)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:109)
at com.google.firebase.firestore.remote.WatchStream.onNext(WatchStream.java:38)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onNext$com-google-firebase-firestore-remote-AbstractStream$StreamObserver(AbstractStream.java:119)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver$$ExternalSyntheticLambda3.run(Unknown Source:4)
at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onNext(AbstractStream.java:110)
at com.google.firebase.firestore.remote.FirestoreChannel.onMessage(FirestoreChannel.java:131)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInternal(ClientCallImpl.java:656)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInContext(ClientCallImpl.java:641)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:234)
at java.lang.Thread.run(Thread.java:923)
V/FA: Inactivity, disconnecting from the service
W/Firestore: (24.0.0) [WatchStream]: (9a4fb5d) Stream closed with status: Status{code=CANCELLED, description=Disconnecting idle stream. Timed out waiting for new targets., cause=null}.
我不知道问题出在哪里。我什至尝试更改安全规则,但仍然出现缺少权限的错误。
还有其他建议吗?
Firestore security rules
打开 Firebase 控制台,然后单击您的项目。
单击屏幕左侧的 Firestore。
在 Firestore 页面上,单击“规则”选项卡。
用以下规则替换现有规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /customers/{customerID} {
allow read:
if request.auth.uid != null
&& request.auth.token.firebase.sign_in_provider == "google.com"
&& request.auth.token.email == customerID
}
}
}
此规则授予客户集合的只读权限。该规则验证您是否已通过您在 Identity Platform 中配置的 Google 登录提供程序登录。它还确保您只能检索客户 ID 与您的电子邮件地址匹配的文档。
注意:无论请求是检索单个文档还是执行查询,对 Firestore 的请求始终根据数据库安全规则进行评估。
- 点击发布。
这里有两个单独的子句:
allow read;
allow write: if request.auth != null;
对于write
你要求用户进行身份验证,但是对于阅读你没有指定条件,这显然意味着不允许阅读。
我的猜测是您希望 if
子句应用于读取和写入,您可以这样做:
allow read, write: if request.auth != null;
我不确定根本问题是什么,但删除 google-services.json 并重新下载后,问题似乎已解决。