简体   繁体   中英

Why retrieving Data from Firebase database doesn't work with user Auth rule But work with anonymous rule?

(NOTE: user have to log in to view the activity and that's implemented and working fine)

(UPDATE: I updated my code to working code, which I hope would help others who struggled in retrieving values under nested push unique key generated by firebase push() --Check the picture under User_location to get what i mean--)

I'll be very detailed to ensure that you guys are getting me. First of all, I tried my code without user auth by setting database rules as following,(it worked perfectly fine and I was able to retrieve my data from Firebase and see them.)

{
  "rules": {

        ".write": true,
        ".read": true
      }
    }

Then, when I set my rules up as the following:( I got an error)

{
  "rules": {
    "users": {
      "$uid": {
        ".write": "$uid === auth.uid",
        ".read": "$uid === auth.uid"
      }
    }
  }
}

This is error message (application doesn't crash and activity showing empty white screen):

11-21 04:20:01.424 9820-9820/? W/zygote: Unexpected CPU variant for X86 using defaults: x86
11-21 04:20:01.453 9820-9828/? E/zygote: Failed sending reply to debugger: Broken pipe
11-21 04:20:01.951 9820-9867/? W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
11-21 04:20:01.978 9820-9867/? W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
11-21 04:20:02.081 9820-9867/? W/zygote: Skipping duplicate class check due to unrecognized classloader
11-21 04:20:02.700 9820-9876/com.example.msiuser.atyourservice W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
11-21 04:20:05.139 9820-9820/com.example.msiuser.atyourservice W/StaticLayout: maxLineHeight should not be -1.  maxLines:1 lineCount:1
11-21 04:20:05.303 9820-9820/com.example.msiuser.atyourservice W/StaticLayout: maxLineHeight should not be -1.  maxLines:1 lineCount:1

                                                                               [ 11-21 04:20:05.342  9820: 9876 D/         ]
                                                                               SurfaceInterface::setAsyncMode: set async mode 1
11-21 04:20:05.482 9820-9820/com.example.msiuser.atyourservice W/View: requestLayout() improperly called by android.widget.ListView{337754f VFED.VC.. .F....ID 0,207-1080,1260 #7f080079 app:id/list} during layout: running second layout pass

Here's my code: (layout.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>

My Java class:

public class AddressBook extends AppCompatActivity { private static final String TAG = "AddressBook";

FirebaseDatabase database;
DatabaseReference myRef;
DatabaseReference myRef2;
private String userID;
private ListView liv;
private ArrayList<String> user_addresses = new ArrayList<>();
private ArrayAdapter<String> adapter;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;

@Override
protected void onCreate(Bundle savedIntancesState) {

    super.onCreate(savedIntancesState);
    setContentView(R.layout.activity_addressbook_listview);

    liv = (ListView) findViewById(R.id.lv);
    mAuth = FirebaseAuth.getInstance();
    database= FirebaseDatabase.getInstance();
    myRef = database.getReference("User_Location");
    final FirebaseUser user = mAuth.getCurrentUser();


    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());

                adapter = new ArrayAdapter<String>(AddressBook.this, android.R.layout.simple_list_item_1, user_addresses);
                liv.setAdapter(adapter);
                myRef.addChildEventListener(new ChildEventListener() {
                    @Override
                    //How to retrieve data under nested push unique key that made by firebase..

                    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                         for (DataSnapshot location : dataSnapshot.getChildren()) {
                            String value = location.child("location").getValue(String.class);
                            user_addresses.add(value);
                            adapter.notifyDataSetChanged();
                        }

                    }

                    @Override
                    public void onChildChanged(DataSnapshot dataSnapshot, String s) {

                    }

                    @Override
                    public void onChildRemoved(DataSnapshot dataSnapshot) {
                        for (DataSnapshot location : dataSnapshot.getChildren()) {
                            String value = location.child("location").getValue(String.class);
                            user_addresses.remove(value);
                            adapter.notifyDataSetChanged();
                        }
                    }

                    @Override
                    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
                // User is signed in
            } else {
                // User is signed out
                Log.d(TAG, "onAuthStateChanged:signed_out");
                toastMessage("Successfully signed out.");
            }
            // ...
        }
    };


   }

@Override
public void onStart() {
    super.onStart();
    mAuth.addAuthStateListener(mAuthListener);
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthListener != null) {
        mAuth.removeAuthStateListener(mAuthListener);
    }
}



private void toastMessage(String message){
    Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}

}

So basically as you can see in the code above, I'm trying to retrieve children of child "User_Location", It contains User unique Uid and it's child location unique id. To make it clear here how I structured my data:

1- users :

在此处输入图片说明

2- location:

在此处输入图片说明

3-User_Location (link each user with their loctions since one user can save multiple locations)

在此处输入图片说明

Please, tell me where I went wrong..

enter image description here

Your code attaches to myRef = database.getReference("User_Location") , but your rules give read permission on /users/$uid . So the read is rejected.

To make the listener work, ensure the user has permission to read the location that you attach the listener to. So:

{
  "rules": {
    "User_Location": {
      ".read": "auth.uid !== null"
    }
  }
}

You might be tempted to try this:

{
  "rules": {
    "User_Location": {
      "$uid": {
        ".write": "$uid === auth.uid",
        ".read": "$uid === auth.uid"
      }
    }
  }
}

But attaching a listener to /User_Location will still be rejected with the above rules, since you're not granting read permission on /User_Location . It is a common with to use security rules to filter data in this way, but rules are not filters . To learn more about this, read some of the many questions about this topic .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM