我应该使用返回用户ID并在Firebase中创建我自己的用户对象,还是不需要这种复制。我确实需要添加一些其他用户属性,所以也许无论如何我都需要这样做。
#1 楼
在Firebase身份验证(以前称为Firebase SimpleLogin)中使用电子邮件/密码身份验证时,用户的电子邮件和密码组合将与实际存储在Firebase中的数据分开安全地存储。您的Firebase和用户的电子邮件/密码哈希组合是有意设计的:我们希望使您更容易(1)开发您的应用程序,(2)防止任何意外的用户凭证泄漏,并且(3)仍然为您提供了全面的灵活性有关如何在Firebase中存储用户数据的说明。
这意味着我们仅存储电子邮件地址/密码哈希组合,而没有其他内容,因此由您决定如何在其中存储实际用户数据您的Firebase。如您所建议,您应该获取用户ID并将该数据存储在Firebase中的/ users / $ id等位置,并使用Firebase安全规则语言确定对该数据的读/写访问。用户的唯一
id
和email
已经在编写规则时要使用的auth
变量中。#2 楼
在这里,我创建了一个Android程序来执行Rob对Firebase初学者(如我)所说的操作。该程序首先存储signedUp或signedIn用户的用户名,然后将它们显示在listViewSignInActivity中。 java
public class SignInActivity extends BaseActivity implements View.OnClickListener,View.OnKeyListener{
private DatabaseReference mDatabase;
public static FirebaseAuth mAuth;
private static final String TAG = "MainActivity";
EditText usernameField;
EditText passwordField;
TextView changeSignUpModeTextView;
Button signUpButton;
ImageView logo;
RelativeLayout relativeLayout;
Boolean signUpModeActive;
static ArrayList<String> userList = new ArrayList<>();
@Override
public void onStart() {
super.onStart();
// Check auth on Activity start
if (mAuth.getCurrentUser() != null) {
onAuthSuccess(mAuth.getCurrentUser());
}
}
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if(i == keyEvent.KEYCODE_ENTER && keyEvent.getAction() == keyEvent.ACTION_DOWN){
signUpOrLogIn(view);
}
return false;
}
@Override
public void onClick(View view) {
if(view.getId() == R.id.changeSignUpMode){
if (signUpModeActive == true){
signUpModeActive = false;
changeSignUpModeTextView.setText("Sign Up");
signUpButton.setText("Log In");
}else{
signUpModeActive = true;
changeSignUpModeTextView.setText("Log In");
signUpButton.setText("Sign Up");
}
}else if(view.getId() == R.id.logo || view.getId() == R.id.relativeLayout){
InputMethodManager inm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
}
}
public void signUpOrLogIn(View view) {
showProgressDialog();
String email = usernameField.getText().toString().trim();
String password = passwordField.getText().toString().trim();
if (signUpModeActive == true) {
mAuth.createUserWithEmailAndPassword(email,password)
.addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
hideProgressDialog();
Toast.makeText(MainActivity.this, "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Toast.makeText(MainActivity.this, "Authentication failed." + task.getException().toString().substring(task.getException().toString().indexOf(" ")),
Toast.LENGTH_SHORT).show();
Log.i("Error", task.getException().toString());
} else {
onAuthSuccess(task.getResult().getUser());
showUserList();
}
}
});
} else {
mAuth.signInWithEmailAndPassword(email,password)
.addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
hideProgressDialog();
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
// there was an error
Toast.makeText(MainActivity.this, task.getException().toString(),
Toast.LENGTH_LONG).show();
} else
{
onAuthSuccess(task.getResult().getUser());
showUserList();
}
}
});
}
}
public void showUserList(){
startActivity(new Intent(getApplicationContext(), UserList.class));
finish();
}
private void onAuthSuccess(FirebaseUser user) {
String username = usernameFromEmail(user.getEmail());
// Write new user
writeNewUser(user.getUid(), username, user.getEmail());
// Go to MainActivity
}
private String usernameFromEmail(String email) {
if (email.contains("@")) {
return email.split("@")[0];
} else {
return email;
}
}
private void writeNewUser(String userId, String name, String email) {
User user = new User(name, email);
mDatabase.child("users").child(userId).setValue(user);
ArrayList<String> userNames = new ArrayList<>();
userNames.add(name);
mDatabase.child("usernamelist").setValue(userNames);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
mDatabase = FirebaseDatabase.getInstance().getReference();
if(mAuth.getCurrentUser()!=null){
showUserList();
}
usernameField = (EditText) findViewById(R.id.username);
passwordField = (EditText) findViewById(R.id.password);
changeSignUpModeTextView = (TextView) findViewById(R.id.changeSignUpMode);
signUpButton = (Button) findViewById(R.id.signupbutton);
logo = (ImageView)findViewById(R.id.logo);
relativeLayout= (RelativeLayout)findViewById(R.id.relativeLayout);
signUpModeActive = true;
changeSignUpModeTextView.setOnClickListener(this);
usernameField.setOnKeyListener(this);
passwordField.setOnKeyListener(this);
logo.setOnClickListener(this);
relativeLayout.setOnClickListener(this);
}
}
UserList.java
public class UserList extends AppCompatActivity {
private static final String TAG = "UserList" ;
private DatabaseReference userlistReference;
private ValueEventListener mUserListListener;
ArrayList<String> usernamelist = new ArrayList<>();
ArrayAdapter arrayAdapter;;
ListView userListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_list);
userlistReference = FirebaseDatabase.getInstance().getReference().child("usernamelist");
onStart();
userListView = (ListView) findViewById(R.id.userlistview);
}
@Override
protected void onStart() {
super.onStart();
final ValueEventListener userListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usernamelist = new ArrayList<>((ArrayList) dataSnapshot.getValue());
usernamelist.remove(usernameOfCurrentUser());
Log.i(TAG, "onDataChange: "+usernamelist.toString());
arrayAdapter = new ArrayAdapter(UserList.this,android.R.layout.simple_list_item_1,usernamelist);
userListView.setAdapter(arrayAdapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "onCancelled: ",databaseError.toException());
Toast.makeText(UserList.this, "Failed to load User list.",
Toast.LENGTH_SHORT).show();
}
};
userlistReference.addValueEventListener(userListener);
mUserListListener = userListener;
}
public String usernameOfCurrentUser()
{
String email = MainActivity.mAuth.getCurrentUser().getEmail();
if (email.contains("@")) {
return email.split("@")[0];
} else {
return email;
}
}
@Override
public void onStop() {
super.onStop();
// Remove post value event listener
if (mUserListListener != null) {
userlistReference.removeEventListener(mUserListListener);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.action_logout:
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(this, MainActivity.class));
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
#3 楼
您可以使用Google Identity Toolkit API来获取Firebase项目中所有注册用户的列表,Firebase CLI使用此API,可以通过运行firebase auth:export results-file
来访问该API。确保已启用Identity Toolkit API
firebase-users-list.js
const serviceAccount = require('path/to/firebase-sdk-json-service-account');
const googleapis = require('googleapis');
const identitytoolkit = googleapis.identitytoolkit('v3');
const authClient = new googleapis.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
['https://www.googleapis.com/auth/firebase'],
null
);
authClient.authorize((err) => {
if (err) {
return console.error(err);
}
let nextPageToken = undefined;
let users = [];
const getAccounts = () => identitytoolkit.relyingparty.downloadAccount({
auth: authClient,
resource: {
targetProjectId: serviceAccount.project_id,
maxResults: 200,
nextPageToken: nextPageToken
}
}, (e, results) => {
if (e) {
return console.error(err);
}
users = users.concat(results.users);
if (results.nextPageToken) {
nextPageToken = results.nextPageToken;
return getAccounts();
} else {
console.log(users);
}
});
getAccounts();
});
#4 楼
可以使用云功能来获取用户列表(在firebase上查看文档)。请注意,在以下示例中,自定义声明功能用于检查用户是否具有足够的特权。// USERS: return full users list for admin
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
import * as admin from 'firebase-admin'
import * as functions from 'firebase-functions'
export const listUsers = functions.https.onCall((data, context) => {
// check if user is admin (true "admin" custom claim), return error if not
const isAdmin = context.auth.token.admin === true
if (!isAdmin) {
return { error: `Unauthorized.` }
}
return admin
.auth()
.listUsers()
.then((listUsersResult) => {
// go through users array, and deconstruct user objects down to required fields
const result = listUsersResult.users.map((user) => {
const { uid, email, photoURL, displayName, disabled } = user
return { uid, email, photoURL, displayName, disabled }
})
return { result }
})
.catch((error) => {
return { error: 'Error listing users' }
})
})
#5 楼
您可以使用admin.auth().listUsers
做到这一点这里的文档是这样的:https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth.html#listusers
以及用法示例:https://firebase.google.com/docs/auth/admin/manage-users#list_all_users
function listAllUsers(nextPageToken) {
// List batch of users, 1000 at a time.
admin.auth().listUsers(1000, nextPageToken)
.then(function(listUsersResult) {
listUsersResult.users.forEach(function(userRecord) {
console.log('user', userRecord.toJSON());
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
})
.catch(function(error) {
console.log('Error listing users:', error);
});
}
// Start listing users from the beginning, 1000 at a time.
listAllUsers();
#6 楼
python中的用户列表: from firebase_admin import credentials, db, auth
cred = credentials.Certificate('\path\to\serviceAccountKey.json')
default_app = firebase_admin.initialize_app(cred, {
"databaseURL": "https://data_base_url.firebaseio.com"
})
users = auth.list_users()
#7 楼
我将尽可能简单地回答通过使用以下代码将注册用户添加到您的数据库中
,您还可以使用共享的首选项将数据保存到本地,但不会
将用户列表保存在数据库中后,只需使用适配器从那里检索它即可。
FirebaseDatabase.getInstance().getReference().child("my_user")
.child(task.getResult().getUser().getUid())
.child("username").setValue(autoCompleteTextView1.getText().toString());
评论
感谢您提供的信息-但是我认为这里存在依赖性,如果我为每个用户存储的数据不同步,例如被意外删除,我怎么知道谁当前可以访问我的应用程序?数据是分开的,但是由于我无法从管理POV中看到它而被否定了,这很好吗?
– markbarton
2013年2月5日14:22
列出所有创建的用户并删除用户看起来是必须具备的!
– Misha Moroshko
13年2月17日在12:32
通过控制台可访问的用户列表现在又回到了新的Google Firebase中
–华金·尤尔丘克(Joaquin Iurchuk)
16年6月18日在21:39
这是必须具备的...如果admin SDK无法横扫用户,Kinda就会破坏用户数据库的目的。
– Rojuinex
17年5月16日在2:24
感谢您的回答弗兰克。但是,如果您要讨论的单独的用户数据库仅存储电子邮件/密码组合(不存储任何其他用户信息),那么为什么在“管理器用户”部分(firebase.google.com/docs/auth/web/manage-users)下进行他们提到可以保存displayName和photoURL的user.updateProfile方法吗?那么此信息将存储在哪里?它没有保存在我的Firestore中-我检查了-所以我假设它在那个单独的数据库中。如果当前用户是唯一可以看到此方法的用户,该方法有什么意义?
– dwilt
17年6月6日在16:42