请求。auth。uid!=null
在使用Firestore安全规则时始终为null。
当uid为null时,Android客户端上的用户通过Firebase UI登录,并显示在Firestore身份验证控制台中。
service cloud.firestore {
function signedInOrPublic() {
return request.auth.uid != null;
}
match /databases/{database}/documents {
match /{document=**} {
allow read;
}
}
// Add to user collection.
match /databases/{database}/documents {
match /users/{userId}/{collectionOrAction}/{content} {
allow create: if signedInOrPublic();
}
}
该呼叫按预期工作,没有任何严格的规则设置。
usersCollection.document(userId).collection(actionCollection)
.document(content.id)
.set(ContentAction(Date(), content.id, content.title, content.creator,
content.qualityScore)).addOnSuccessListener {
updateUserActionCounter(userId, countType)
}.addOnFailureListener {
Log.w(LOG_TAG, "User content action update FAIL.")
}
implementation 'com.firebase:firebase-client-android:2.5.2'
implementation 'com.google.firebase:firebase-core:16.0.3'
implementation 'com.google.firebase:firebase-firestore:17.1.0'
implementation 'com.firebaseui:firebase-ui-firestore:4.1.0'
implementation 'com.firebaseui:firebase-ui-auth:4.0.0'
我有一个版本的谷歌服务。json用于我的调试和发布版本,以便为应用程序的生产版本保留单独的Firestore项目/环境/分析。我想知道这是否会影响Firestore规则,即使到目前为止Firebase的其他部分(Firestore db、Analytics等)都按预期运行此设置。
应用程序
应用程序
请求。Firestore规则文件中的auth
不为空李> 请求。auth。uid==userId
,在上面比较请求的规则中。auth。uid
到路径路由中的用户ID
李> 请求。auth。代币电子邮件==用户电子邮件
,规则失败李> implementation'com。谷歌。firebase:firebase认证:16.0。4
实现'com。谷歌。Androidgms:play services授权:16.0。1'
firebase firestore:17.1。1
,firebase ui firestore:4.2。0,firebase用户界面验证:4.1。0
李> 在示例应用程序中,有一个登录/退出按钮,可根据用户当前的登录状态对其进行登录和退出。登录状态显示在左上角。“获取数据”按钮根据Firestore安全规则从Firestore数据库检索字符串字段。
2018-10-14 15:21:59.123 24192-24192/firebase_security_sample.adamhurwitz.firebasesecuritysample
E/AndroidRuntime: FATAL EXCEPTION: main
Process: firebase_security_sample.adamhurwitz.firebasesecuritysample, PID: 24192
com.google.android.gms.tasks.RuntimeExecutionException: com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
at com.google.android.gms.tasks.zzu.getResult(Unknown Source:15)
at firebase_security_sample.adamhurwitz.firebasesecuritysample.MainActivity$onCreate$2$1.onComplete(MainActivity.kt:63)
at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
at com.google.firebase.firestore.obfuscated.zzhc.zza(com.google.firebase:firebase-firestore@@17.1.1:119)
at com.google.firebase.firestore.obfuscated.zzk.zza(com.google.firebase:firebase-firestore@@17.1.1:134)
at com.google.firebase.firestore.obfuscated.zzak.zza(com.google.firebase:firebase-firestore@@17.1.1:384)
at com.google.firebase.firestore.obfuscated.zzm.zza(com.google.firebase:firebase-firestore@@17.1.1:235)
at com.google.firebase.firestore.obfuscated.zzfv.zza(com.google.firebase:firebase-firestore@@17.1.1:7521)
at com.google.firebase.firestore.obfuscated.zzfv$1.zza(com.google.firebase:firebase-firestore@@17.1.1:172)
at com.google.firebase.firestore.obfuscated.zzgc.zzb(com.google.firebase:firebase-firestore@@17.1.1:3109)
at com.google.firebase.firestore.obfuscated.zzfh.run(com.google.firebase:firebase-firestore@@17.1.1:1117)
at com.google.firebase.firestore.obfuscated.zzfc$zza.zza(com.google.firebase:firebase-firestore@@17.1.1:67)
at com.google.firebase.firestore.obfuscated.zzfc$zzc.zza(com.google.firebase:firebase-firestore@@17.1.1:110)
at com.google.firebase.firestore.obfuscated.zzgv$1.onMessage(com.google.firebase:firebase-firestore@@17.1.1:107)
at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33)
at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:526)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
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.obfuscated.zzgf$zza.run(com.google.firebase:firebase-firestore@@17.1.1:203)
at java.lang.Thread.run(Thread.java:764)
Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions.
at io.grpc.Status.asException(Status.java:534)
at com.google.firebase.firestore.obfuscated.zzhc.zza(com.google.firebase:firebase-firestore@@17.1.1:117)
at com.google.firebase.firestore.obfuscated.zzk.zza(com.google.firebase:firebase-firestore@@17.1.1:134)
at com.google.firebase.firestore.obfuscated.zzak.zza(com.google.firebase:firebase-firestore@@17.1.1:384)
at com.google.firebase.firestore.obfuscated.zzm.zza(com.google.firebase:firebase-firestore@@17.1.1:235)
at com.google.firebase.firestore.obfuscated.zzfv.zza(com.google.firebase:firebase-firestore@@17.1.1:7521)
at com.google.firebase.firestore.obfuscated.zzfv$1.zza(com.google.firebase:firebase-firestore@@17.1.1:172)
at com.google.firebase.firestore.obfuscated.zzgc.zzb(com.google.firebase:firebase-firestore@@17.1.1:3109)
at com.google.firebase.firestore.obfuscated.zzfh.run(com.google.firebase:firebase-firestore@@17.1.1:1117)
at com.google.firebase.firestore.obfuscated.zzfc$zza.zza(com.google.firebase:firebase-firestore@@17.1.1:67)
at com.google.firebase.firestore.obfuscated.zzfc$zzc.zza(com.google.firebase:firebase-firestore@@17.1.1:110)
at com.google.firebase.firestore.obfuscated.zzgv$1.onMessage(com.google.firebase:firebase-firestore@@17.1.1:107)
at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33)
at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:526)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
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.obfuscated.zzgf$zza.run(com.google.firebase:firebase-firestore@@17.1.1:203)
at java.lang.Thread.run(Thread.java:764)
service cloud.firestore {
match /databases/{database}/documents {
match /testCollection/testDoc {
allow read: if request.auth.uid != null
}
}
}
buildscript {
ext.kotlin_version = '1.2.71'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
defaultConfig {
applicationId "firebase_security_sample.adamhurwitz.firebasesecuritysample"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.android.gms:play-services-auth:16.0.1'
implementation 'com.google.firebase:firebase-core:16.0.4'
implementation 'com.google.firebase:firebase-auth:16.0.4'
implementation 'com.google.firebase:firebase-firestore:17.1.1'
implementation 'com.firebaseui:firebase-ui-firestore:4.2.0'
implementation 'com.firebaseui:firebase-ui-auth:4.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
apply plugin: 'com.google.gms.google-services'
class MainActivity : AppCompatActivity() {
lateinit var signInStatus: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
FirebaseApp.initializeApp(
this,
FirebaseOptions.Builder()
.setApplicationId("1:63924060965:android:c387085babd1a8a4") // Required for Analytics.
.setApiKey("AIzaSyCi4h6WBX495xmzaRsLYro2_Vd9UcB3bpg") // Required for Auth.
.setDatabaseUrl("https://security-rules-sample.firebaseio.com") // Required for RTDB.
.setProjectId("security-rules-sample")
.build(),
"firestoreSecuritySample")
signInStatus = findViewById(R.id.signInStatus) as TextView
val user = FirebaseAuth.getInstance().currentUser
if (user != null) {
signInStatus.text = user.displayName
} else {
signInStatus.text = "logged out"
}
signInButton.setOnClickListener {
if (FirebaseAuth.getInstance().currentUser == null) {
val providers = Arrays.asList<AuthUI.IdpConfig>(
AuthUI.IdpConfig.GoogleBuilder().build())
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
123)
} else {
AuthUI.getInstance().signOut(this).addOnCompleteListener {
signInStatus.text = "logged out"
}
}
}
getDataButton.setOnClickListener {
FirebaseFirestore.getInstance(FirebaseApp.getInstance("firestoreSecuritySample"))
.collection("testCollection").document("testDoc").get().addOnCompleteListener {
if (FirebaseAuth.getInstance().currentUser != null) {
firestoreResult.text = it.result!!.get("testField").toString()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 123) {
if (resultCode == Activity.RESULT_OK) {
val user = FirebaseAuth.getInstance().currentUser
if (user != null) {
signInStatus.text = user.displayName
}
}
}
}
感谢Google开发者关系团队的Sam Stern帮助调试!我已经为上面创建的示例应用程序和正在生产的应用程序测试了下面的修复程序。
我很确定你的问题来自这一行:
Firebase App.get实例("firestoreSecuritySample")您正在使用自定义Firebase App与数据库通信,但登录时没有使用相同的Firebase App。每个应用实例都有一个单独的身份验证状态。
尝试更改登录代码以将应用程序传递到getInstance:
startActivityForResult(
// SEE BELOW FOR CHANGE
> AuthUI.getInstance(FirebaseApp.getInstance("firestoreSecuritySample"))
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
123)