firebase-security документация - Firebase android:уникальное имя пользователя




на русском (4)

Сохраните имена пользователей, как было предложено Фрэнком, но когда вы сохраняете имена пользователей, используйте функцию runTransaction в Firebase, чтобы убедиться, что имя пользователя не принято. Эта функция гарантируется Firebase как атомная операция, поэтому вы можете быть уверены в отсутствии столкновения

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
        }
    }
});

В конце года Parse будет закрыт, поэтому я решил начать использовать Firebase. Мне нужно реализовать процесс регистрации с тремя полями: адрес электронной почты, имя пользователя, пароль ( Email и имя пользователя должны быть уникальными для моего приложения).

Поскольку Firebase не предоставляет простой способ управлять именем пользователя, например Parse, я решил использовать только регистрацию по электронной почте / паролю и сохранить некоторые дополнительные данные, такие как имя пользователя. Вот моя структура данных пользователей:

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

Но я хочу сделать уникальное имя пользователя и проверить его перед созданием учетной записи. Это мои правила:

{
    "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()"}
            }
        }
   }
}

Большое спасибо за Вашу помощь


Я не знаю многого о безопасности firebase, но я, возможно, решил проблему с помощью Java. Я разместил его ниже.

моя структура данных

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];
    }

Часть ответа заключается в том, чтобы хранить индекс имен пользователей, которые вы проверяете в своих правилах безопасности:

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

Таким образом, узел usernames сопоставляет имя пользователя с uid. Он по существу читает, что «имя пользователя« myname »принадлежит« some-user-uid ».

С этой структурой данных ваши правила безопасности могут проверить, есть ли уже запись для данного имени пользователя:

"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"
    }
  }
}

Это подтверждает, что имя пользователя еще не востребовано кем-либо еще, или оно заявлено текущим пользователем.


Я использую пользовательскую клавиатуру для ввода шестнадцатеричного номера, поэтому я не могу открыть клавиатуру IMM ...

В v3.2.4_r1 setSoftInputShownOnFocus(boolean show) был добавлен для управления погодой или не отображать клавиатуру, когда TextView получает фокус, но ее все еще скрыто, поэтому необходимо использовать отражение:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

Для более старых версий я получил очень хорошие результаты (но далеко не идеальный) с помощью OnGlobalLayoutListener , добавленный с помощью ViewTreeObserver из моего корневого представления, а затем проверяя, показана ли клавиатура следующим образом:

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

Это последнее решение может отображать клавиатуру в течение секунды секунды и беспорядок с помощью дескрипторов выделения.

Когда клавиатура входит в полноэкранный режим, onGlobalLayout не вызывается. Чтобы этого избежать, используйте TextView#setImeOptions(int) или в XML-декларации TextView:

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

Обновление: просто нашел, какие диалоги используют, чтобы никогда не показывать клавиатуру и работать во всех версиях:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);




android firebase firebase-security firebase-authentication