【问题标题】:Android: realtime Firebase RulesAndroid:实时 Firebase 规则
【发布时间】:2021-12-20 01:18:57
【问题描述】:

我想知道如何保护我的规则。我尝试在读写中使用auth.uid != null

但是如果一个新用户尝试登录或创建新帐户,它不会成功并且给我的权限被拒绝。

我想保护用户并限制仅对用户本人及其数据的读取:

我尝试使用auth.uid != null,但已经注册用户无法登录,新用户无法创建帐户。所以我必须让公共读写成为现实。有什么解决办法吗?

因为即使是 auth.uid != null ,经过身份验证的用户可以读取所有用户的全部数据,而不仅仅是他自己

这是我的规则副本:

{
  "rules": {
    ".write": "root.child('Admins').child(auth.uid).exists()",
    "Admins": {
      ".read": true,
      ".write": false
    },
    "Users": {
      ".read": true,
        ".write": true 
    },
    "PrivateWork": {
      ".read": "auth.uid != null",
        ".write": false
    },
    "Likes": {
      ".read": "auth.uid != null",
        ".write": "auth.uid != null"
    },
    "Work": {
      ".read": "auth.uid != null",
        ".write": false
    },
    "videos": {
      ".read": "auth.uid != null",
        ".write": false
    }
  }
}

注册活动:

//Check if num already exist
binding.continueBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (binding.phoneNumBox.getText().toString().isEmpty()) {
            binding.phoneNumBox.setError(getString(R.string.please_enter_phone));
        } else if (binding.phoneNumBox.getText().toString().length() < 6) {
            binding.phoneNumBox.setError(getString(R.string.enter_valid_phone));
        } else {
        DatabaseReference userRef = FirebaseDatabase.getInstance().getReference("Users");
        userRef.orderByChild("phoneNumber")
                .equalTo(binding.phoneNumBox.getText().toString())
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot.getValue() != null) {
                            Toast.makeText(RegPhoneNumActivity.this, getString(R.string.already_exist), Toast.LENGTH_SHORT).show();
                        } else {
                                Intent intent = new Intent(RegPhoneNumActivity.this, OTPActivity.class);
                                intent.putExtra("phoneNumber", binding.phoneNumBox.getText().toString());
                                startActivity(intent);
                            }
                        }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
        }
    }
});

登录活动:

//Check if num already exist
binding.loginContinueBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (binding.loginPhoneNumBox.getText().toString().isEmpty()) {
            binding.loginPhoneNumBox.setError(getString(R.string.please_enter_phone_numb));
        } else if (binding.loginPhoneNumBox.getText().toString().length() <= 6) {
            binding.loginPhoneNumBox.setError(getString(R.string.plaese_enter_valid_phone_num));
        } else {
            userRef.orderByChild("phoneNumber")
                    .equalTo(binding.loginPhoneNumBox.getText().toString())
                    .addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            if (dataSnapshot.getValue() != null) {
                                Intent intent = new Intent(PhoneLoginActivity.this, LoginVerifyPhoneActivity.class);
                                intent.putExtra("phoneNumber", binding.loginPhoneNumBox.getText().toString());
                                startActivity(intent);
                            } else {
                                Toast.makeText(PhoneLoginActivity.this, getString(R.string.phone_num_doesnt_exist), Toast.LENGTH_SHORT).show();
                            }
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {

                        }
                    });
        }
    }
});

【问题讨论】:

  • 安全规则自己不会做任何事情;它们只有在您对它们运行代码时才会变得活跃。请编辑您的问题以包含 minimal code too,并确保在该代码中显示它如何满足您的规则中的条件(例如通过记录 UID)。
  • 已更新代码

标签: android firebase-realtime-database firebase-authentication firebase-security


【解决方案1】:

要允许用户仅读取自己的数据,您需要:

  1. 使用用户的 UID 作为其节点的 key
  2. 安全访问,如 content-owner only access 上的文档中所示。

对于意味着您的 Users 节点变成这样的规则:

"Users": {
  "$uid": {
    ".read": "$uid === auth.uid"
  }
},

然后访问它的代码变成:

userRef.child(FirebaseAuth.getInstance().getCurrentUser().getUID())
       .addListenerForSingleValueEvent(new ValueEventListener() {

虽然也可以将登录用户的电话号码与数据库中节点的值进行对比,但用户也必须已经登录。如果您遇到这种情况,请查看securely querying data 上的文档。

【讨论】:

  • 尝试在空对象引用上调用虚拟方法“java.lang.String com.google.firebase.auth.FirebaseUser.getUid()”
  • 当新用户尝试创建帐户甚至尝试登录时会发生这种情况,因为新用户还没有第一次获得 uid
  • 您的"auth.uid != null" 规则表明您只希望登录用户能够写入数据库,因此在用户登录之前尝试写入数据库是没有意义的。
  • true,那么如果我希望新用户可以创建帐户并且已经注册并希望登录以能够仅读取他的数据,那么规则会是什么样子,或者这是不可能的,我需要保留it .read, .write true 表示完全读写,但任何人都可以下载整个用户数据
  • 我的回答中的规则允许用户读取他们自己的数据,如果您将这些数据存储在他们的 UID 下。我的答案中的第一个链接解释了有关该场景的更多信息。
猜你喜欢
  • 2021-12-18
  • 2021-01-31
  • 1970-01-01
  • 2020-08-08
  • 2020-02-16
相关资源
最近更新 更多