私は(Firebaseリアルタイムデータベースのコンテキストでも)この質問何回か見てきましたが、私はそれに納得のいく答えを見ていません。問題の声明はかなり簡単です:
(認証された)ユーザーは、まだ取得されていないユーザー名をどのように選択できますか?まず
、なぜ:ユーザーが認証した後、彼らは固有のユーザーIDを持っています。しかし、多くのWebアプリケーションでは、ユーザーの個人データ(実名など)を保護するために、ユーザーは「表示名」(Webサイトに表示する方法)を選択できます。
ユーザーコレクション
ユーザーごとに他のデータと一緒にユーザー名を格納することができる次のようなデータ構造を考える:
/users (collection)
/{uid} (document)
- name: "<the username>"
- foo: "<other data>"
しかし、何もして(別のユーザーを防ぎません別の{uid}
)は、レコードに同じname
を格納します。私が知る限り、name
がすでに別のユーザーによって使用されているかどうかを確認するための「セキュリティルール」はありません。
注:クライアント側のチェックは可能ですが、悪意のあるクライアントがチェックを省略できるため安全ではありません。
人気のソリューションは、逆マッピングのコレクション作成するリバースマッピング:
/usernames (collection)
/{name} (document)
- uid: "<the auth {uid} field>"
この逆マッピングを考えると、ユーザ名であることを強制するためのセキュリティルールを記述することが可能ですまだ取られていない:
match /users/{userId} {
allow read: if true;
allow create, update: if
request.auth.uid == userId &&
request.resource.data.name is string &&
request.resource.data.name.size() >= 3 &&
get(/PATH/usernames/$(request.resource.data.name)).data.uid == userId;
}
ユーザ名を最初に作成する:
match /usernames/{name} {
allow read: if true;
allow create: if
request.resource.data.size() == 1 &&
request.resource.data.uid is string &&
request.resource.data.uid == request.auth.uid;
}
私は解決策がそこにあると信じています。しかし、まだ解決されていない問題がいくつかあります。
残された課題/質問
この実装は、すでにかなり複雑ですが、それも(ユーザー名を変更したいユーザーの問題等、記録の削除または更新規則が必要では解決しません)
もう1つの問題は、ユーザーがusernames
コレクションに複数のレコードを追加するのを妨げるものではなく、システムを妨害するすべてのユーザー名を効果的に奪ってしまうことはありません。質問に対するので
:
- ユニークユーザ名を強制するために簡単な解決策はありますか?
usernames
コレクションをスパムするのを防ぐにはどうすればよいですか?- ユーザー名の確認で大文字と小文字を区別することはできますか?
私も/ユーザ名の収集のための別のexists()
ルールに、users
の存在を強化して、一括書き込み操作をコミットしようとした、しかし、これは(「がないか不十分な権限」を動作するようには思えませんエラー)。
もう1つの注意:私はクライアント側のチェックで解決策を見てきました。 ですが、これはアンサーフです。悪意のあるクライアントはコードを修正し、チェックを省略することができます。
誰かがtwittertと私は彼が逆引き参照を作成する必要はないことを示唆したと信じて:https://twitter.com/abeisgreat/status/920730970751254528 – crazypeter