22

L'analisi si spegne alla fine dell'anno, quindi ho deciso di iniziare a utilizzare Firebase. Devo implementare un processo di registrazione con 3 campi: email, nome utente, password (Email & nome utente deve essere univoco per la mia app).Firebase Android: crea un nome utente univoco

Dal momento che Firebase non fornisce un modo semplice per gestire il nome utente come Parse, ho deciso di utilizzare solo la registrazione email/password e di salvare alcuni dati aggiuntivi come il nome utente. Qui è la mia struttura dati degli utenti:

app : { 
    users: { 
     "some-user-uid": { 
      email: "[email protected]" 
      username: "myname" 
     } 
    } 
} 

Ma, quello che voglio fare è quello di rendere il nome utente unico e per verificare prima di creare un account. Queste sono le mie regole:

{ 
    "rules": { 
     ".read": true, 
     ".write": true, 
     "users": { 
      "$uid": { 
       ".write": "auth !== null && auth.uid === $uid", 
       ".read": "auth !== null && auth.provider === 'password'", 
       "username": {".validate": "!root.child('users').child(newData.child('username').val()).exists()"} 
      } 
     } 
    } 
} 

La ringrazio molto per il vostro aiuto

+0

Quindi vuoi controllare le regole di Firebase sul client Android? –

+0

Sì, voglio controllare prima se il nome utente viene preso se firebase mi dice no, quindi creare un account altrimenti basta chiedere all'utente di scegliere un altro nome utente – FloGz

+1

Oltre alla mia risposta sulla struttura dei dati e le regole di sicurezza, ecco alcune domande dove l'argomento ha è stato trattato in precedenza: http://stackoverflow.com/questions/29970681/enforcing-unique-usernames-with-firebase-simplelogin, http://stackoverflow.com/questions/25294478/how-do-you-prevent-duplicate- user-properties-in-firebase, http://stackoverflow.com/questions/15910165/usernames-with-firebase-simple-login-email-password, http://stackoverflow.com/questions/20260476/what-firebase- rule-will-prevenire-duplicates-in-a-collection-based-on-other-fields –

risposta

36

Parte della risposta è quello di memorizzare un indice di nomi utente, che si controlla contro nelle regole di sicurezza:

app : { 
    users: { 
     "some-user-uid": { 
      email: "[email protected]" 
      username: "myname" 
     } 
    }, 
    usernames: { 
     "myname": "some-user-uid" 
    } 
} 

Quindi il nodo usernames associa un nome utente a un uid. In sostanza si legge come "username 'myname' è di proprietà di 'some-user-uid'".

Con questa struttura dati, le regole di sicurezza può controllare se esiste già una voce per un determinato nome utente:

"users": { 
    "$uid": { 
    ".write": "auth !== null && auth.uid === $uid", 
    ".read": "auth !== null && auth.provider === 'password'", 
    "username": { 
     ".validate": " 
     !root.child('usernames').child(newData.val()).exists() || 
     root.child('usernames').child(newData.val()).val() == $uid" 
    } 
    } 
} 

Ciò conferma che il nome utente non è sostenuto da nessuno eppure O si sostiene dal utente attuale.

+1

ottima risposta, duplicativa con http://stackoverflow.com/questions/25294478/how-do-you-prevent-duplicate-user -properties-in-firebase – Creos

+4

Ciao Frank, penso che sarebbe anche importante nota che probabilmente dovresti eseguire tutti i controlli su 'nomi utente 'in caratteri minuscoli e memorizzare lettere minuscole, in questo modo non puoi avere nomi utente identici di casi diversi. Il valore memorizzato nel campo 'users/some-user-uid/username' può essere case sensitive, che può essere la versione leggibile, che dovrebbe consentire una selezione del nome utente più user friendly e l'aderenza al caso. –

+0

@Frank van Puffelen puoi confermare ciò che Viv sta dicendo sulla sua risposta sull'utilizzo di una Transection invece di una normale query set? Inoltre, qualsiasi regex che hai scritto prima può essere utilizzata per convalidare i caratteri consentiti per i nomi utente? – Relm

-3

Non so ancora molto sulla sicurezza di Firebase, ma potrei aver risolto il problema utilizzando Java. L'ho pubblicato qui sotto.

mia struttura dati è

myapp 
{ 
    users: { 
      <unique generated-id> 
      { username: "example.username" } 
} 
} 


public boolean isUsernameExists(final String enteredUsername) { 
     final Boolean[] isExist = {false}; 
     FBref.child("users").addValueEventListener(new ValueEventListener() { 
      @Override 
      public void onDataChange(DataSnapshot dataSnapshot) { 
       for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) { 
        String existingUsername = (String) userSnapshot.child("userName").getValue(); 
        if (existingUsername.equals(enteredUsername)) { 
         isExist[0] = true; 
        } 
       } 
      } 
      @Override 
      public void onCancelled(FirebaseError firebaseError) { 
       //some error thrown here 
      } 
     }); 
     return isExist[0]; 
    } 
3

Salva nomi utente come suggerito da Frank, ma quando si salva nomi utente, utilizzare la funzione runTransaction in Firebase per assicurarsi che il nome utente non è stata presa. Questa funzione è garantita da Firebase per essere un'operazione atomica in modo che tu possa essere certo di nessuna collisione

firebaseRef.child("usernames").child(username).runTransaction(new Transaction.Handler() { 
    @Override 
    public Transaction.Result doTransaction(MutableData mutableData) { 
     if (mutableData.getValue() == null) { 
      mutableData.setValue(authData.getUid()); 
      return Transaction.success(mutableData); 
     } 

     return Transaction.abort(); 
    } 

    @Override 
    public void onComplete(FirebaseError firebaseError, boolean commited, DataSnapshot dataSnapshot) { 
     if (commited) { 
      // username saved 
     } else { 
      // username exists 
     } 
    } 
}); 
+0

L'hai impostato nell'elenco dei nomi utente ma non in uid. Dovremmo aggiungere una riga completa per farlo? – user2997154

Problemi correlati