Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/207.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java “问题”;“拒绝许可”;在Firestore上根据安全规则获取_Java_Android_Google Cloud Firestore_Firebase Security - Fatal编程技术网

Java “问题”;“拒绝许可”;在Firestore上根据安全规则获取

Java “问题”;“拒绝许可”;在Firestore上根据安全规则获取,java,android,google-cloud-firestore,firebase-security,Java,Android,Google Cloud Firestore,Firebase Security,如果用户必须注册,我的Android Java应用程序首先使用AuthUI.getInstance()创建Firebase帐户(带密码的电子邮件)。创建帐户时,会出现一个对话框,通知用户他收到了一封验证电子邮件,他必须单击电子邮件中的验证链接。当用户完成此操作后,他可以关闭对话框并继续在Firestore中配置他的帐户 但是Firestore文档上的所有请求都受安全规则保护,如 allow read: if request.auth.uid != null && request.

如果用户必须注册,我的Android Java应用程序首先使用
AuthUI.getInstance()
创建Firebase帐户(带密码的电子邮件)。创建帐户时,会出现一个对话框,通知用户他收到了一封验证电子邮件,他必须单击电子邮件中的验证链接。当用户完成此操作后,他可以关闭对话框并继续在Firestore中配置他的帐户

但是Firestore文档上的所有请求都受安全规则保护,如

allow read: if request.auth.uid != null && request.auth.token.email != null && request.auth.token.email_verified == true;
失败

com.google.firebase.firestore.FirebaseFirestoreException:权限\被拒绝:权限缺失或不足

如果用户关闭应用程序,重新启动应用程序并重新验证,则其工作正常(Firestore请求的权限没有问题)

我做了几次测试。如果我将安全规则更改为

allow read: if request.auth.uid != null && request.auth.token.email != null;
一切正常,但从我的角度来看,它不太安全,因为没有保证电子邮件是经过验证的。Firestore似乎仍不知道该帐户已验证

以下是一项活动的示例:

package foo;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import com.firebase.ui.auth.AuthUI;
import com.google.android.gms.tasks.Task;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.firebase.Timestamp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QuerySnapshot;
import com.google.firebase.firestore.Source;
import com.google.firebase.functions.FirebaseFunctions;
import com.google.firebase.functions.HttpsCallableReference;
import com.google.firebase.functions.HttpsCallableResult;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

import fr.cinfo.planartis.R;

public class ExampleActivity extends AppCompatActivity {
    private static final int SIGN_IN_REQUEST_CODE = 123;
    private static final String VERIFICATION_EMAIL_SENT_TIMESTAMP_KEY = "verificationEmailSentTimestamp";
    private FirebaseAuth firebaseAuth;
    private FirebaseFirestore firestore;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        firebaseAuth = FirebaseAuth.getInstance();
        firestore = FirebaseFirestore.getInstance();

        if (firebaseAuth.getCurrentUser() == null) {
            startUserSignInActivity();
        } else {
            performEmailVerification();
        }
    }

    void startUserSignInActivity() {
        startActivityForResult(
            AuthUI.getInstance()
                .createSignInIntentBuilder()
                .setAvailableProviders(Collections.singletonList(new AuthUI.IdpConfig.EmailBuilder().build()))
                .setIsSmartLockEnabled(false, true)
                .setTosAndPrivacyPolicyUrls("https://localhost/terms.html", "https://localhost/privacy.html")
                .build(),
            SIGN_IN_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
        if (requestCode == SIGN_IN_REQUEST_CODE) {
            if (resultCode != RESULT_OK) { // ERRORS
                // ... do something
                finish();
                return;
            }
            performEmailVerification();
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    void performEmailVerification() {
        if (firebaseAuth.getCurrentUser().isEmailVerified()) {
            // Everything is OK
            checkSomethingOnFirestore();
            return;
        }

        final DocumentReference documentReference = firestore.document("users/" + firebaseAuth.getCurrentUser().getEmail());
        documentReference.get(Source.DEFAULT).addOnCompleteListener((Task<DocumentSnapshot> task) -> {
            if (task.isSuccessful()) {
                final DocumentSnapshot userSnapshot = task.getResult();
                if (userSnapshot.exists()) {
                    // Check if the first verification email was sent
                    final Object timestamp = userSnapshot.get(VERIFICATION_EMAIL_SENT_TIMESTAMP_KEY);
                    if (timestamp == null) {
                        firebaseAuth.getCurrentUser().sendEmailVerification().addOnCompleteListener((Task<Void> validationEmailTask) -> {
                            if (validationEmailTask.isSuccessful()) {
                                final Timestamp now = Timestamp.now();
                                documentReference.update(VERIFICATION_EMAIL_SENT_TIMESTAMP_KEY, now).addOnCompleteListener((Task<Void> updateUserAccountTask) -> {
                                    if (!updateUserAccountTask.isSuccessful()) {
                                    }
                                    displayWarningAboutValidation();
                                });
                            }
                            else {
                                // email not sent, so display message
                                FirebaseAuth.getInstance().signOut();
                                displayInformationDialog(this, "Unable to send a verification email", null).show();
                                finish();
                            }
                        });
                    }
                    else {
                        displayWarningAboutValidation();
                    }
                }
                else {
                    Toast.makeText(this, "We are finalizing your account creation\nPlease wait a few seconds", Toast.LENGTH_LONG).show();
                    final HttpsCallableReference httpsCallableReference = FirebaseFunctions.getInstance().getHttpsCallable("finalizeUserAccount");
                    httpsCallableReference.setTimeout(15, TimeUnit.SECONDS);
                    httpsCallableReference.call(firebaseAuth.getCurrentUser().getEmail()).continueWith((Task<HttpsCallableResult> task12) -> {
                        if (!task12.isSuccessful()) {
                            displayInformationDialog(this, "The finalization of your account failed.", (DialogInterface dialog, int id) -> {
                                FirebaseAuth.getInstance().signOut();
                                finish();
                            }).show();
                            return null;
                        }

                        displayInformationDialog(this, "A new verification email was sent", (final DialogInterface dialog, final int id) -> {
                            // Reload current user
                            firebaseAuth.getCurrentUser().reload().addOnCompleteListener((Task<Void> task1) -> {
                                if (task1.isSuccessful()) {
                                    performEmailVerification();
                                }
                                else {
                                    FirebaseAuth.getInstance().signOut();
                                    finish();
                                }
                            });

                        });
                        return null;
                    });
                }
            }
            else {
                displayInformationDialog(this, "Problem with the server", (DialogInterface dialog, int id) -> {
                    FirebaseAuth.getInstance().signOut();
                    finish();
                }).show();
            }
        });
    }

    private void checkSomethingOnFirestore() {
        firestore.collection("users").document(firebaseAuth.getCurrentUser().getEmail()).collection("documents").get().addOnCompleteListener(this, (Task<QuerySnapshot> task) -> {
            if (!task.isSuccessful()) {  // <======================================== PERMISSION_DENIED exception !!!!!!
                displayInformationDialog(this, "Problem on Firestore", (final DialogInterface dialog, final int id) -> {
                    FirebaseAuth.getInstance().signOut();
                    finish();
                })
                .show();
                return;
            }
            // Go on and do the job: for instance display the GUI or anything else
        });
    }

    private void displayWarningAboutValidation() {
        new AlertDialog.Builder(this)
            .setCancelable(false)
            .setMessage("Read the verification email we sent and click on the link inside the email")
            .setPositiveButton("I understand", (DialogInterface dialog, int id) -> firebaseAuth.getCurrentUser().reload().addOnCompleteListener((Task<Void> task) -> {
                if (task.isSuccessful()) {
                    performEmailVerification();
                }
                else {
                    FirebaseAuth.getInstance().signOut();
                    finish();
                }
            }))
            .setNeutralButton("Send back a verification email", (final DialogInterface dialog, final int which) -> firebaseAuth.getCurrentUser().sendEmailVerification().addOnCompleteListener((final Task<Void> task) -> {
                dialog.dismiss();
                if (task.isSuccessful()) {
                    // email sent
                    displayInformationDialog(this, "A new verification email was sent", (final DialogInterface dialog12, final int which12) -> {
                        FirebaseAuth.getInstance().signOut();
                        finish();
                    }).show();

                    firebaseAuth.getCurrentUser().reload().addOnCompleteListener((Task<Void> task1) -> {
                        if (task1.isSuccessful()) {
                            performEmailVerification();
                        }
                        else {
                            FirebaseAuth.getInstance().signOut();
                            finish();
                        }
                    });
                }
                else {
                    // email not sent, so display message
                    displayInformationDialog(this, "Unable to send a new verification email", (final DialogInterface dialog1, final int which1) -> {
                        FirebaseAuth.getInstance().signOut();
                        finish();
                    }).show();
                }
            }))
            .show();
    }

    private AlertDialog displayInformationDialog(final Context context, final CharSequence message, final DialogInterface.OnClickListener positiveButtonOnclickListener) {
        return new MaterialAlertDialogBuilder(context).setCancelable(false).setMessage(message).setPositiveButton("I understand", positiveButtonOnclickListener).setTitle("Planartis").setIcon(R.drawable.ic_logo_toolbar).show();
    }

}
package-foo;
导入android.content.Context;
导入android.content.DialogInterface;
导入android.content.Intent;
导入android.os.Bundle;
导入android.widget.Toast;
导入androidx.annotation.Nullable;
导入androidx.appcompat.app.AlertDialog;
导入androidx.appcompat.app.appcompat活动;
导入com.firebase.ui.auth.AuthUI;
导入com.google.android.gms.tasks.Task;
导入com.google.android.material.dialog.materialAllertDialogBuilder;
导入com.google.firebase.Timestamp;
导入com.google.firebase.auth.FirebaseAuth;
导入com.google.firebase.firestore.DocumentReference;
导入com.google.firebase.firestore.DocumentSnapshot;
导入com.google.firebase.firestore.FirebaseFirestore;
导入com.google.firebase.firestore.QuerySnapshot;
导入com.google.firebase.firestore.Source;
导入com.google.firebase.functions.FirebaseFunctions;
导入com.google.firebase.functions.httpscalableReference;
导入com.google.firebase.functions.httpscalableresult;
导入java.util.Collections;
导入java.util.concurrent.TimeUnit;
进口fr.cinfo.PLANATIS.R;
公共类ExampleActivity扩展了AppCompativity{
请求代码中的私有静态最终整数符号=123;
私有静态最终字符串验证\u电子邮件\u发送\u时间戳\u KEY=“verificationEmailSentTimestamp”;
私有FirebaseAuth FirebaseAuth;
私人FirebaseFirestore firestore;
@凌驾
创建时受保护的void(最终捆绑包savedInstanceState){
super.onCreate(savedInstanceState);
firebaseAuth=firebaseAuth.getInstance();
firestore=FirebaseFirestore.getInstance();
如果(firebaseAuth.getCurrentUser()==null){
startusersignitivity();
}否则{
performEmailVerification();
}
}
void startuservignitivity(){
startActivityForResult(
AuthUI.getInstance()
.CreateSignInEntBuilder()
.setAvailableProviders(Collections.singletonList(新的AuthUI.IdpConfig.EmailBuilder().build())
.setIsSmartLockEnabled(假、真)
.setTosAndPrivacyPolicyUrls(“https://localhost/terms.html", "https://localhost/privacy.html")
.build(),
在请求代码中签名;
}
@凌驾
受保护的void onActivityResult(最终int请求代码、最终int结果代码、@Nullable最终意图数据){
if(requestCode==在请求代码中签名){
如果(resultCode!=RESULT\u OK){//错误
//…做点什么
完成();
返回;
}
performEmailVerification();
}否则{
super.onActivityResult(请求代码、结果代码、数据);
}
}
作废PerformMailVerification(){
if(firebaseAuth.getCurrentUser().isEmailVerified()){
//一切都好
checkSomethingOnFirestore();
返回;
}
final DocumentReference=firestore.document(“users/”+firebaseAuth.getCurrentUser().getEmail());
documentReference.get(Source.DEFAULT).addOnCompleteListener((任务)->{
if(task.issusccessful()){
final DocumentSnapshot userSnapshot=task.getResult();
if(userSnapshot.exists()){
//检查是否发送了第一封验证电子邮件
最终对象时间戳=userSnapshot.get(验证\电子邮件\发送\时间戳\密钥);
if(时间戳==null){
firebaseAuth.getCurrentUser().sendEmailVerification().addOnCompleteListener((任务验证邮件任务)->{
if(validationEmailTask.isSuccessful()){
final Timestamp now=Timestamp.now();
documentReference.update(验证\电子邮件\发送\时间戳\密钥,现在)。addOnCompleteListener((任务updateUserAccountTask)->{
如果(!updateUserAccountTask.isSuccessful()){
}
显示警告BoutValidation();
});
}
否则{
//电子邮件未发送,因此显示消息
FirebaseAuth.getInstance().signOut();
displayInformationDialog(此“无法发送验证电子邮件”,null).show();
完成();
}
});
}
否则{
显示警告BoutValidation();
}
}
否则{
Toast.makeText(这是“我们正在完成您的帐户创建\n区域
void performEmailVerification() {
    if (firebaseAuth.getCurrentUser().isEmailVerified()) {
        // Everything is OK, perform your task
        checkSomethingOnFirestore();
        return;
    }
    
    //User not verified, but you still get a database reference and try to get the email.
    final DocumentReference documentReference = ... //Error produced 
FirebaseAuth.getInstance().getCurrentUser().reload();