问题
I am new to firebase , but I managed to develop an app using firebase -email&password authentication This app is for an organization's members so there is no sign up on the app , the organization gives me a list which I add to user list.My problem here is , I have only 45 registered users ,but there are almost 85 who are using the app.I understand I should be using an auth token , but I am not quite clear.Can anybody explain the easiest way I could prevent multiple logins simultaneously ? I have attached the login code ( I tried storing device names , but was a bad way )so can anybody please help me out on what has to be done?
public class EmailLogin extends AppCompatActivity implements
View.OnClickListener {
public String Email;
private static final String TAG = "EmailPassword";
public static int device = 0;
private TextView forgoPwd;
private TextView mDetailTextView;
private EditText mEmailField;
private EditText mPasswordField;
private ProgressDialog PD;
private CheckBox saveLoginCheckBox;
private SharedPreferences loginPreferences;
private SharedPreferences.Editor loginPrefsEditor;
private Boolean saveLogin;
// [START declare_auth]
private FirebaseAuth mAuth;
// [END declare_auth]
private DatabaseReference root;
// [START declare_auth_listener]
private FirebaseAuth.AuthStateListener mAuthListener;
// [END declare_auth_listener]
private String temp_key;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.emailpass);
PD = new ProgressDialog(this);
PD.setMessage("Loading...");
PD.setCancelable(true);
PD.setCanceledOnTouchOutside(false);
// Views
mEmailField = (EditText) findViewById(R.id.field_email);
Email = mEmailField.toString();
mPasswordField = (EditText) findViewById(R.id.field_password);
Button btnCount = (Button) findViewById(R.id.email_sign_in_button);
// Button regis = (Button) findViewById(R.id.regis);
saveLoginCheckBox = (CheckBox)findViewById(R.id.checkBox);
loginPreferences = getSharedPreferences("loginPrefs", MODE_PRIVATE);
loginPrefsEditor = loginPreferences.edit();
saveLogin = loginPreferences.getBoolean("saveLogin", false);
if (saveLogin == true) {
mEmailField.setText(loginPreferences.getString("username", ""));
mPasswordField.setText(loginPreferences.getString("password", ""));
saveLoginCheckBox.setChecked(true);
}
//regis.setOnClickListener(this);
forgoPwd = (TextView)findViewById(R.id.forgo);
forgoPwd.setOnClickListener(this);
// Buttons
btnCount.setOnClickListener(this);
// findViewById(R.id.email_create_account_button).setOnClickListener(this);
// findViewById(R.id.sign_out_button).setOnClickListener(this);
// [START initialize_auth]
mAuth = FirebaseAuth.getInstance();
// [END initialize_auth]
// [START auth_state_listener]
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());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// [START_EXCLUDE]
updateUI(user);
// [END_EXCLUDE]
}
};
// [END auth_state_listener]
}
public ProgressDialog mProgressDialog;
public void showProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.loading));
mProgressDialog.setIndeterminate(true);
}
}
public void hideProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
}
// [START on_start_add_listener]
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
// [END on_start_add_listener]
// [START on_stop_remove_listener]
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
// [END on_stop_remove_listener]
private void createAccount(String email, String password) {
Log.d(TAG, "createAccount:" + email);
if (!validateForm()) {
return;
}
showProgressDialog();
// [START create_user_with_email]
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "createUserWithEmail:onComplete:" + task.isSuccessful());
// 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(EmailLogin.this, R.string.auth_failed,
Toast.LENGTH_SHORT).show();
}
// [START_EXCLUDE]
hideProgressDialog();
// [END_EXCLUDE]
}
});
// [END create_user_with_email]
}
private void signIn(String email, String password) {
Log.d(TAG, "signIn:" + email);
if (saveLoginCheckBox.isChecked()) {
loginPrefsEditor.putBoolean("saveLogin", true);
loginPrefsEditor.putString("username", mEmailField.getText().toString());
loginPrefsEditor.putString("password", password);
loginPrefsEditor.commit();
} else {
loginPrefsEditor.clear();
loginPrefsEditor.commit();
}
if (!validateForm()) {
return;
}
PD.show();
showProgressDialog();
// [START sign_in_with_email]
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithEmail:onComplete:" + task.isSuccessful());
if (task.isSuccessful())
{
onAuthSuccess(task.getResult().getUser());
}
// 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()) {
Log.w(TAG, "signInWithEmail:failed", task.getException());
Toast.makeText(EmailLogin.this, R.string.auth_failed,
Toast.LENGTH_SHORT).show();
}
// [START_EXCLUDE]
if (!task.isSuccessful()) {
// mStatusTextView.setText(R.string.auth_failed);
}PD.dismiss();
hideProgressDialog();
// [END_EXCLUDE]
}
});
// [END sign_in_with_email]
}
private void onAuthSuccess(FirebaseUser user) {
if (device == 0)
getDeviceName();
device++;
String username = usernameFromEmail(user.getEmail());
Intent intent = new Intent(getApplicationContext(),Home_screen.class);
intent.putExtra("user",username);
startActivity(intent);
finish();
}
public String getDeviceName() {
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
root = FirebaseDatabase.getInstance().getReference().child("users");
doDb(manufacturer);
return manufacturer+model ;
}
private void doDb(String manu) {
Map<String,Object> map = new HashMap<String, Object>();
temp_key = root.push().getKey();
root.updateChildren(map);
DatabaseReference mess_root = root.child(temp_key);
Map<String,Object> map2 = new HashMap<String, Object>();
String email = FirebaseAuth.getInstance().getCurrentUser().getEmail();
int index = email.indexOf('@');
email = email.substring(0,index);
map2.put("user",email);
map2.put("msg",manu);
mess_root.updateChildren(map2);
}
private String usernameFromEmail(String email) {
if (email.contains("@")) {
return email.split("@")[0];
} else {
return email;
}
}
private void signOut() {
mAuth.signOut();
updateUI(null);
}
private boolean validateForm() {
boolean valid = true;
String email = mEmailField.getText().toString();
if (TextUtils.isEmpty(email)) {
mEmailField.setError("Required.");
valid = false;
} else {
mEmailField.setError(null);
}
String password = mPasswordField.getText().toString();
if (TextUtils.isEmpty(password)) {
mPasswordField.setError("Required.");
valid = false;
} else {
mPasswordField.setError(null);
}
return valid;
}
private void updateUI(FirebaseUser user) {
hideProgressDialog();
if (user != null) {
//Timer timer = new Timer();
//timer.schedule(new TimerTask(){
// public void run() {
Intent i = new Intent(EmailLogin.this, Home_screen.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
// return;
// }
// }, 600000);
}
/*
if (user != null) {
Intent intent = new Intent(getApplicationContext(),Home_screen.class);
startActivity(intent);
finish();
mStatusTextView.setText(getString(R.string.emailpassword_status_fmt, user.getEmail()));
mDetailTextView.setText(getString(R.string.firebase_status_fmt, user.getUid()));
findViewById(R.id.email_password_buttons).setVisibility(View.GONE);
findViewById(R.id.email_password_fields).setVisibility(View.GONE);
} */
else {
// mStatusTextView.setText(R.string.signed_out);
// mDetailTextView.setText(null);
// findViewById(R.id.email_password_buttons).setVisibility(View.VISIBLE);
// findViewById(R.id.email_password_fields).setVisibility(View.VISIBLE);
}
}
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.email_sign_in_button) {
signIn(mEmailField.getText().toString(), mPasswordField.getText().toString());
}
//if(i == R.id.regis)
{
}
if(i == R.id.forgo) {
FirebaseAuth auth = FirebaseAuth.getInstance();
String mail = mEmailField.getText().toString();
if (TextUtils.isEmpty(mail)) {
mEmailField.setError("Required.");
} else {
auth.sendPasswordResetEmail(mEmailField.getText().toString())
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(EmailLogin.this, "Email sent to your account",
Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
}
回答1:
I understand I should be using an auth token
That won't work. Whenever a user signs in on a device, they get a new auth token. So the same user being signed in on two devices, will have to different auth tokens.
But they will have the same UID. So I'd actually store the uid and something that identifies the active device in the database.
activeDeviceByUser
<uid>: <device ID>
Then remove that when the user signs out or disconnects.
回答2:
You can employ a session manager, which just keeps track of the last session and terminates all other sessions for that user. A simple way to accomplish this is to generate a UUID (random 128-bit value) on the client every time your app launches and call it sessionId
. If the user is logged in, or when the user logs in, write that sessionId
to the database under the current user's userId
in a field called lastSessionId
. Then just listen for changes to lastSessionId
(on the client) for the current userId
.
When another client launches your app using the same userId
, that client is also given a random sessionId
and that sessionId
is also written to the database under that userId
(overriding the last client's write). All of the clients logged into that userId
are then notified of the change to lastSessionId
(through the document listener) and for every client where the local sessionId
does not match the remote lastSessionId
, their UX is handled accordingly. You can gracefully sign those clients out or more brutally terminate their app with some sort of fatal error.
来源:https://stackoverflow.com/questions/43360516/how-to-prevent-same-user-logging-in-from-different-devices-my-app-is-paid-so