如何知道哪个用户正在尝试登录? [英] How to know which user is trying to Sign-in?

查看:140
本文介绍了如何知道哪个用户正在尝试登录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



用户使用电子邮件和密码创建。这是我如何做注册:
$ b $ pre $ code> mSignup.setOnClickListener(new View.OnClickListener(){
@覆盖
public void onClick(View v){

mEmailStr = removeSpaces(mEmail.getText()。toString());
mPasswordStr = mPassword.getText()。toString( );
mUsernameStr = mUsername.getText()。toString();
mIsSgl = mSglCheckBox.isChecked();
mUsernameStr = mUsername.getText()。toString();
最终用户mUser = new User();
mUser.setEmail(mEmailStr);
mUser.setPassword(mPasswordStr);
mUser.setIsSgl(mIsSgl);
mUser.setStudyGroupName mStoreGroupName);
mUser.setUsername(mUsernameStr);
FirebaseAuth.getInstance()。createUserWithEmailAndPassword(mUser.getEmail(),mUser.getPassword())。addOnCompleteListener(new OnCompleteListener< AuthResult>(){
@O verride
public void onComplete(Task< AuthResult>任务){


if(task.isSuccessful()){
Toast.makeText(getActivity(),Sucsses,Toast.LENGTH_SHORT).show();
generateUser(mUser);
startActivity(new Intent(getActivity(),MainActivity.class));
} else {
Toast.makeText(getActivity(),not Sucsses,Toast.LENGTH_SHORT).show();
}
}
});



}
});

这是我将数据推送到数据库的方式:
$ b $ FireBase数据库= FirebaseDatabase.getInstance(); b $ {pre> public void generateUser(User user)
{

FirebaseDatabase database = FirebaseDatabase.getInstance
DatabaseReference用户;
if(user.getIsSgl())
{
users = database.getReference(user.getStudyGroupName())。child(SGL);

else

users = database.getReference(user.getStudyGroupName())。child(Student);
}

users.push()。setValue(user);




这是我如何登入:


$ b $ pre $ mSignin.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){

mEmailStr = SignupActivityFragment.removeSpaces(mEmail.getText()。toString());
mPasswordStr = mPassword.getText()。toString();

mAuth。 signInWithEmailAndPassword(mEmailStr,mPasswordStr).addOnCompleteListener(getActivity(),new OnCompleteListener< AuthResult>(){
@Override $ b $ public void onComplete(Task< AuthResult> task){
if ()){


FirebaseDatabase数据库= FirebaseDatabase.getInstance();
//那些工作对我来说
database.getReference(StudyGroups)。子( 学生)。orderByChild( 电子邮件)。equalT o(mEmailStr).addListenerForSingleValueEvent(new DataEventListener(){
@Override
public void onDataChange(DataSnapshot dataSnapshot){
for(DataSnapshot childSnapShot:dataSnapshot.getChildren()){
userKey = childSnapShot.getKey();
}

Toast.makeText(getContext(),Userkey:+ userKey,Toast.LENGTH_LONG).show();
Log.v(himaAbousalem,userKey);
}

@Override
public void onCancelled(DatabaseError databaseError){

$ b});
Toast.makeText(getActivity(),Sucsses,Toast.LENGTH_SHORT).show();
startActivity(new Intent(getActivity(),Controller.class));
} else {
Toast.makeText(getActivity(),not sucsses,Toast.LENGTH_SHORT).show();
}

}
});
}
});

我想查询数据库,以便当用户通过电子邮件和密码登录时,它会返回如何在Auth中将 userId 的关键字设置为等于数据库中的 userId ,以及如何使用该功能?

解决方案

tl; dr - 在这种情况下,使用由Firebase Auth生成的关联 uid 来存储每个用户,而不是使用推送ID。在您的情况下,使用推送ID来存储特定于每个用户的信息的挑战是,当用户登录你不知道你第一次存储他们的信息时使用的推送ID。要在用户每次登录时查找用户,必须搜索数据库中的每个用户,直到找到匹配的电子邮件/密码来检索其正确的个人资料信息 - 用户越多,搜索所需的时间就越长。另一个可能更快的方法是使用Firebase身份验证来创建用户和Firebase数据库,以存储任何用户特定的信息。



当您创建新用户时Firebase身份验证会为用户分配一个唯一的用户ID,在用户的整个生命周期内都是一样的。然后,您使用由Firebase身份验证生成的唯一用户标识,而不是推送标识来将用户信息存储在数据库中。下次用户登录时,从Firebase身份验证中获取用户的 uid ,并使用它查询数据库以获取该用户的信息。



查看指南,了解如何创建基于密码的用户以及如何使用Firebase身份验证签署用户:

为了使用唯一的 uid 由Firebase身份验证生成我建议对您的代码进行一些更改。


$ b 更新数据库结构



我建议你在创建/登录用户时添加一个新的位置(也许是allUsers)来更新你的数据库结构。现在看起来你正在把学生分成几组。如果你需要保持这种结构,由于认证以外的原因,你可以使用它和我的建议。存储所有用户的单个位置的原因在于,您需要一个确定的位置来查询用户登录时的情况。使用Firebase身份验证时,如果没有存储所有用户的单个位置,则无法确定用户属于哪个组当他们第一次登录的时候,你必须检查每个小组以便找到一个匹配,这可能需要很长时间。有一个存储所有用户的位置解决了这个问题。而且,从单个位置检索用户信息的查询要简单得多。如果你确实需要在多个地方保存一个用户的信息,那么只要有任何改变,就要确保在两个地方更新他们的信息。

创建一个类变量区分创建用户和登录现有用户。

如果您使用相同的活动来创建新用户并登录现有用户,布尔变量来区分何时创建新用户和何时现有用户正在登录。它将稍后在 AuthStateListener 中使用。如果你在一般的登录单独的活动中处理用户创建,那么你不应该需要这个变量,因为每个活动都有一个独立的 AuthStateListener

  boolean mIsNewUser = false; 

将调用createUser()从create user completion listener移至AuthStateListener。还要将数据库查询从登录完成监听器移动到AuthStateLisener



无论您何时成功创建用户,他们也会自动登录。因此,如果您将调用从 createUserWithEmailAndPassword OnCompleteListener 移动到 generateUser() c $ c>到你的 AuthStateListener ,你可以访问创建的用户的 uid 。当对现有用户进行签名时,也将数据库查询移动到 AuthStateListener ,所以我们可以访问用户的 uid 。我还将为数据库查询创建一个名为 getExistingUserInfo 的帮助程序方法。作为参考,用于创建和登录用户的 onComplete()回调在 OnCompleteListeners 中可以访问 AuthResult 根据API有一个返回当前用户的方法,但是文档说要访问 AuthStateListener

  private FirebaseAuth mAuth; 
私有FirebaseAuth.AuthStateListener mAuthListener;

@Override
protected void onCreate(Bundled savedInstanceState){
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener(){
@Override $ b $ public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth){
FirebaseUser user = firebaseAuth.getCurrentUser();
if(user!= null){
//用户登录
Log.d(TAG,onAuthStateChanged:signed_in:+ user.getUid());

if(mIsNewUser){
//使用Uid生成用户而不是pushID
generateUser(mUser,user.getUid());
} else {
getExistingUserInfo(user.getUid());
}
startActivity(new Intent(getActivity(),MainActivity.class));
} else {
//用户签出
Log.d(TAG,onAuthStateChanged:signed_out);
}
// ...
}
};
// ...
}
}

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


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



$ b $ p $更新你的generateUser()辅助方法到使用uid而不是推送ID:

我会假设您想保留现有的数据库结构并为所有用户添加单个位置如建议。基于此,我已经对 generateUser()中使用的写入操作进行了一些更改。主要不是使用 setValue()写入数据库,而是使用 updateChildren()。通过使用 updateChildren(),我们可以利用Firebase进行原子更新的功能。这将允许我们写入适当的学生组位置和同时存储所有用户的位置。通过采取这种方法,如果对任一位置的写入操作失败,则两个位置都不会被更新。这样,您可以确定学生是否被添加到一个组中,他们也将被列在allUsers位置。

  private void generateUser(User user,String uid)
{

DatabaseReference database = 。FirebaseDatabase.getInstance()getReference();
字符串userType;
字符串allusers =allUsers /+ uid;
地图< String,Object> newUserUpdate = new HashMap<>();
if(user.getUsername()!= null){
if(user.isSgl()){
userType = user.getStudyGroupName()+/+SGL+ /+ uid;
} else {
userType = user.getStudyGroupName()+/+Student+/+ uid;
}

newUserUpdate.put(userType,user.serialize());
newUserUpdate.put(allusers,user.serialize());
database.updateChildren(newUserUpdate);





$ b

更新数据库查询以使用新的位置存储所有用户

如上所述,通过为所有用户创建单个位置,可以降低用于查找用户信息的查询的复杂度他们登录。同样,如果您需要按组保存用户,则可以保留该用户,但如果用户信息发生更改,请务必更新两个位置。

  public void getExistingUserInfo(String uid){

FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference(allUsers)。child(uid).addListenerForSingleValueEvent(new ValueEventListener(){
@Override
public void onDataChange(DataSnapshot dataSnapshot){
// get用户数据dataSnapshot

Toast.makeText(getContext(),Userkey:+ userKey,Toast.LENGTH_LONG).show();
Log.v(himaAbousalem,userKey) ;
}

@Override
public void onCancelled(DatabaseError databaseError){


});





$ b

设置用于区分现有用户的变量登录和创建用户完成监听器中的新用户

  FirebaseAuth.getInstance()。createUserWithEmailAndPassword(mUser。 getEmail(),mUser.getPassword())。addOnCompleteListener(new OnCompleteListener< AuthResult>(){
@Override $ b $ public void onComplete(Task< AuthResult> task){

if(task.isSuccessful()){

//在AuthListener中使用set boolean
mIsNewUser = true;
Toast.makeText(getActivity(),Sucsses,Toast .LENGTH_SHORT).show();

} else {
Toast.makeText(getActivity(),not Sucsses,Toast.LENGTH_SHORT).show();
}
}
});


Users are created using Email and Password. This is how I do the Sign-up:

    mSignup.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            mEmailStr = removeSpaces(mEmail.getText().toString());
            mPasswordStr = mPassword.getText().toString();
            mUsernameStr = mUsername.getText().toString();
            mIsSgl = mSglCheckBox.isChecked();
            mUsernameStr=mUsername.getText().toString();
            final User mUser = new User();
            mUser.setEmail(mEmailStr);
            mUser.setPassword(mPasswordStr);
            mUser.setIsSgl(mIsSgl);
            mUser.setStudyGroupName(mStudyGroupName);
            mUser.setUsername(mUsernameStr);
            FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(Task<AuthResult> task) {


                    if (task.isSuccessful()) {
                        Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
                        generateUser(mUser);
                        startActivity(new Intent(getActivity(), MainActivity.class));
                    } else {
                        Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
                    }
                }
            });



        }
    });

This is how I push the data into database:

 public void generateUser(User user)
  {

    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference users;
    if(user.getIsSgl())
    {
        users = database.getReference(user.getStudyGroupName()).child("SGL");
    }
    else
    {
        users = database.getReference(user.getStudyGroupName()).child("Student");
    }

    users.push().setValue(user);

}

This is how I Sign-in:

mSignin.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            mEmailStr = SignupActivityFragment.removeSpaces(mEmail.getText().toString());
            mPasswordStr = mPassword.getText().toString();

            mAuth.signInWithEmailAndPassword(mEmailStr, mPasswordStr).addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(Task<AuthResult> task) {
                    if (task.isSuccessful()){


                        FirebaseDatabase database = FirebaseDatabase.getInstance();                            
                        // thats not worked for me
                        database.getReference("StudyGroups").child("Student").orderByChild("email").equalTo(mEmailStr).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                for (DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
                                    userKey = childSnapShot.getKey();
                                }

                                Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
                                Log.v("himaAbousalem",userKey);
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });
                        Toast.makeText(getActivity(), "Sucsses ", Toast.LENGTH_SHORT).show();
                        startActivity (new Intent(getActivity(),Controller.class));
                    }else {
                        Toast.makeText(getActivity(), "not sucsses", Toast.LENGTH_SHORT).show();
                    }

                }
            });
        }
    });

I want to query the database so that when a user signs-in by Email and password, it returns all the data of that user from the database.

How can I make the key of userId in Auth equal to the userId in database and how do I use that feature?

解决方案

tl;dr - In this case, store each user using their associated uid generated by Fireabase Auth instead of using a push ID.


In your situation the challenge with using a push ID to store info specific to each user is that when a user signs in you don't know the push ID you used when you first stored their info. To find a user each time they sign in you would have to search through every user in your database until you find a matching email/password to retrieve their correct profile information - the more users you have, the longer it would take to do the search. One alternative, which would probably be faster, is to use Firebase Authentication to create users and the Firebase Database to store any user specific information.

When you create a new user using Firebase Authentication it will assign a unique user id to the user that will be the same throughout the lifetime of the user. You then use the unique user id generated by Firebase Auth instead of a push ID to store user info in the database. The next time a user signs in you get the user's uid from Firebase Auth and use it to query the database to get that user's information.

Check the guide for how to create a password-based user and how to sign a user in using Firebase Auth: Create a password-based account

In order to use the unique uid generated by Firebase Auth I suggest a few changes to your code.

Update database structure

I suggest you update your database structure by adding a new location (maybe "allUsers") for use when you create/sign in users. Right now it looks like your are breaking up students into groups. If you need to keep this structure, for reasons beyond authentication, you can use it along with my suggestion. The reason for a single location which stores all users is that you need a definite location to query when a user signs in. When using Firebase Auth, without a single location which stores all users there is no way to tell what group a user belongs to when they first sign in. You would have to check every group in order to find a match and that may take a long time. Having a location which stores all users solves that problem. Also, the query for retrieving user information from that single location is much simpler. If you do need to keep a user's information in multiple places just be sure to update their information in both places if any changes occur.

Create a class variable used to distinguish between create user and sign in existing user.

If you use the same Activity to create a new user and sign in an existing user then create a boolean variable to make a distinction between when a new user is being created and when an existing user is signing in. It will be used later in the AuthStateListener. If you handle user creation in a separate activity from general sign in then you shouldn't need this variable because each activity would have a separate AuthStateListener.

boolean mIsNewUser = false; 

Move the call to generateUser() from the create user completion listener to an AuthStateListener. Also move your database query from the sign in completion listener to the AuthStateLisener

Whenever you create a user successfully they will automatically be signed in too. So, if you move your call to generateUser() from the createUserWithEmailAndPassword OnCompleteListener to your AuthStateListener you can get access to the created user's uid. When signing an existing user move your database query to the AuthStateListener as well, again so we can access the user's uid. I'm also going to create a helper method for the database query called getExistingUserInfo. As an FYI, the onComplete() callback in the OnCompleteListeners for creating and signing in users gives you access to an AuthResult which according to the API has a method for returning the current user but the documentation says to access user information in the AuthStateListener.

private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    mAuth = FirebaseAuth.getInstance();
    mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());

                    if(mIsNewUser){
                        //call to generate user using Uid instead of pushID
                        generateUser(mUser, user.getUid());
                    } else{
                        getExistingUserInfo(user.getUid());
                    }
                    startActivity(new Intent(getActivity(), MainActivity.class));
                } else {
                    // User is signed out
                    Log.d(TAG, "onAuthStateChanged:signed_out");
                }
                // ...
            }
        };
        // ...
    }
}

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

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

Update your generateUser() helper method to use the uid instead of a push ID:

I'm going to assume you want to keep you existing database structure and add the single location for all users as suggested. Based on this I've made a couple of changes to the write operation you were using in generateUser(). Mainly, instead of using setValue() to write to the database I'm using updateChildren(). By using updateChildren() we can take advantage of Firebase's ability to do atomic updates. This will allow us to write to the appropriate student group location and the location storing all users simultaneously. By taking this approach if the write operation to either location fails neither location will be updated. This way you can be certain if a student is added to a group they will also be listed in the allUsers location.

private void generateUser(User user, String uid)
  {

      DatabaseReference database = FirebaseDatabase.getInstance().getReference();
    String userType;
    String allusers = "allUsers/" + uid;
    Map<String, Object> newUserUpdate = new HashMap<>();
    if (user.getUsername() != null) {
        if (user.isSgl()) {
            userType = user.getStudyGroupName() + "/" + "SGL" + "/" + uid;
        } else {
            userType = user.getStudyGroupName() + "/" + "Student" + "/" + uid;
        }

        newUserUpdate.put(userType, user.serialize());
        newUserUpdate.put(allusers, user.serialize());
        database.updateChildren(newUserUpdate);
    }    
    }

Update database query to use new location which stores all users

As I mentioned above, by creating a single location for all users you can reduce the complexity of the query used to find a user's info when they sign in. Again, if you need to store users by group you can keep that but be sure to update both locations if a users info changes.

public void getExistingUserInfo(String uid){

 FirebaseDatabase database = FirebaseDatabase.getInstance(); 
                        database.getReference("allUsers").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                //get user data from dataSnapshot

                                Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
                                Log.v("himaAbousalem",userKey);
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });

}

Set the variable used to distinguish between existing user sign in and new user creation in the create user completion listener

FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(Task<AuthResult> task) {

                    if (task.isSuccessful()) {

                        //set boolean used in the AuthListener
                        mIsNewUser = true;
                        Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();

                    } else {
                        Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
                    }
                }
            });

这篇关于如何知道哪个用户正在尝试登录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆