Firebase データベース セキュリティ ルール API

ルール: タイプ

。読む

クライアントに Firebase Realtime Database の場所への読み取りアクセスを許可します。

.readルールは、クライアントに Firebase Realtime Database の場所への読み取りアクセスを許可するセキュリティ ルールの一種です。例えば:

 ".read": "auth != null && auth.provider == 'twitter'"

.readルールの値は文字列であり、明確さと正確性を高めるために動作がいくつか変更された JavaScript の式構文のサブセットとして評価されます。場所の読み取り権限を付与する.readルールは、その子孫に失敗する独自の.readルールがある場合でも、その場所の子孫の読み取りも許可します。

.readルールは、 newDataを除く Firebase Realtime Database のすべてのルール変数にアクセスできます。

。書く

クライアントに Firebase Realtime Database の場所への書き込みアクセスを許可します。

.writeルールは、クライアントに Firebase Realtime Database の場所への書き込みアクセスを許可するセキュリティ ルールの一種です。例えば:

".write": "auth != null && auth.token.isAdmin == true"

.writeルールの値は文字列であり、明確さと正確性を高めるために動作がいくつか変更された JavaScript の式構文のサブセットとして評価されます。ある場所への書き込み権限を付与する.writeルールは、その子孫に独自の.writeルールがあり失敗した場合でも、その場所の子孫への書き込みも許可します。

.writeルールは、Firebase Realtime Database のすべてのルール変数にアクセスできます。

。検証

.writeルールがアクセスを許可すると、書き込まれるデータが特定のスキーマに準拠していることを確認するために使用されます。

.validateルールがアクセスを許可すると、 .writeルールが使用され、書き込まれるデータが特定の標準に準拠していることを確認します。アクセスを許可する.writeに加えて、書き込みが許可される前に、関連するすべての.validateルールが成功する必要があります。例えば:

".validate": "newData.hasChildren(['name', 'age'])"

.validateルールの値は文字列であり、明確さと正確性を高めるために動作がいくつか変更された JavaScript の式構文のサブセットとして評価されます。

.validateルールは、Firebase Realtime Database のすべてのルール変数にアクセスできます。

.indexOn

データのインデックスを作成するキーを Firebase Realtime Database に伝えることで、クエリのパフォーマンスが向上します。

.indexOnルールは、クエリのパフォーマンスを向上させるためにデータ内の特定のキーにインデックスを付けるように Firebase Realtime Database サーバーに指示します。たとえば、恐竜データのコレクションを含むデータベースがある場合、次のルールを追加することで、サーバーからクエリが返される前にクエリを最適化するように Firebase Realtime Database に指示できます。

{
  "rules": {
    "dinosaurs": {
      ".indexOn": ["height", "length"]
    }
  }
}

.indexOnルールの詳細については、セキュリティ ガイドのデータのインデックス作成に関するセクションを参照してください。

ルール: 変数

認証

クライアントが認証されている場合はトークン ペイロードを含む変数、クライアントが認証されていない場合はnull含む変数。

Firebase Realtime Database を使用すると、いくつかの組み込みプロバイダーに対して簡単に認証でき、それらのプロバイダーの認証トークンを生成できます。ユーザーが組み込みプロバイダーのいずれかで認証されると、auth 変数には次のものが含まれます。

分野説明
provider使用される認証方法 (「パスワード」、「匿名」、「facebook」、「github」、「google」、または「twitter」など)。
uidすべてのプロバイダー間で一意であることが保証された一意のユーザー ID。
token Firebase Auth ID トークンの内容。 auth.token参照してください。

例として、次のようなルールを作成して、ユーザー ID をコメントとともに保存する限り、ユーザーがコメントを作成できるようにすることができます。

{
  "rules": {
    ".read": true,
    "$comment": {
      ".write": "!data.exists() && newData.child('user_id').val() == auth.uid"
    }
  }
}

また、次のようなルールを作成して、ユーザーが Facebook を使用してサインインしている限りコメントを作成できるようにすることもできます。

{
  "rules": {
    ".read": true,
    "$comment": {
      ".write": "!data.exists() && auth.provider == 'facebook'"
    }
  }
}

認証トークン

Firebase Auth ID トークンの内容を含む変数。

トークンには、次のキーの一部またはすべてが含まれています。

分野説明
emailアカウントに関連付けられている電子メール アドレス (存在する場合)。
email_verifiedユーザーがemailアドレスにアクセスできることを確認した場合はtrue 。一部のプロバイダーは、所有する電子メール アドレスを自動的に確認します。
phone_numberアカウントに関連付けられている電話番号 (存在する場合)。
nameユーザーの表示名 (設定されている場合)。
subユーザーの Firebase UID。これはプロジェクト内で一意です。
firebase.identitiesこのユーザーのアカウントに関連付けられているすべての ID の辞書。辞書のキーは、 emailphonegoogle.comfacebook.comgithub.comtwitter.comのいずれかになります。ディクショナリの値は、アカウントに関連付けられた各 ID プロバイダーの一意の識別子の配列です。たとえば、 auth.token.firebase.identities["google.com"][0]アカウントに関連付けられた最初の Google ユーザー ID が含まれています。
firebase.sign_in_providerこのトークンを取得するために使用されるサインイン プロバイダー。次の文字列のいずれかを指定できます: custompasswordphoneanonymousgoogle.comfacebook.comgithub.comtwitter.com
firebase.tenantアカウントに関連付けられた tenantId (存在する場合)。例: tenant2-m6tyz

カスタム認証を使用する場合、 auth.tokenには開発者が指定したカスタム クレームも含まれます。

これらの値はすべてルール内で使用できます。たとえば、gmail.com アドレスに関連付けられた Google アカウントへのアクセスを制限するには、次のルールを追加します。

{
  "rules": {
    ".read": "auth != null",
    "gmailUsers": {
      "$uid": {
        ".write": "auth.token.email_verified == true && auth.token.email.matches(/.*@gmail.com$/)"
      }
    }
  }
}

完全を期すために、 auth.tokenには次のフィールドも含まれていますが、ルールには使用できない可能性があります。

分野説明
issトークンの発行者。
audトークンの対象者。
auth_timeユーザーがトークンを受信するデバイスを使用して資格情報で最後に認証された時刻。
iatトークンが発行された時刻。
expトークンの有効期限が切れる時刻。

$location

ルール構造で以前に使用された$locationのキーを参照するために使用できる変数。

ルール構造に$locationある場合、ルール式内で一致する$変数を使用して、読み書きされる実際の子の名前を取得できます。そこで、すべてのユーザーに各自の/users/<user>の場所への読み取りおよび書き込みアクセスを許可するとします。以下を使用できます:

{
  "rules": {
    "users": {
      "$user": {
        ".read": "auth.uid === $user",
        ".write": "auth.uid === $user"
      }
    }
  }
}

クライアントが/users/barneyにアクセスしようとすると、 $userデフォルトの場所は$user 「barney」に等しいと一致します。したがって、 .readルールはauth.uid === 'barney'かどうかをチェックします。その結果、 /users/barney読み取りは、クライアントが「barney」の uid で認証されている場合にのみ成功します。

Firebase Realtime Database サーバーに基づく Unix エポックからのミリ秒数が含まれます。

now変数には、Firebase Realtime Database サーバーに基づく UNIX エポックからのミリ秒数が含まれます。たとえば、これを使用して、ユーザーがcreated時刻が将来の時刻に設定されないことを検証できます。

{
  "rules": {
    "users": {
      "$user": {
        "created": {
          ".validate": "newData.val() < now"
        }
      }
    }
  }
}

Firebase Realtime Database のルートにある現在のデータに対応するRuleDataSnapshot

ルート変数は、Firebase Realtime Database のルートにある現在のデータに対応するRuleDataSnapshot を提供します。これを使用して、ルール式でデータベース内の任意のデータを読み取ることができます。たとえば、 /users/<id>/active true に設定されている場合にのみ、ユーザーに/comments読み取りを許可したい場合は、次のように使用できます。

{
  "rules": {
    "comments": {
      ".read": "root.child('users').child(auth.uid).child('active').val() == true"
    }
  }
}

次に、 /users/barney/active値 true が含まれている場合、「barney」の uid で認証されたユーザーは/commentsノードに書き込むことができます。

データ

現在実行されているルールの場所にある Firebase Realtime Database 内の現在のデータに対応するRuleDataSnapshot

data 変数は、現在実行中のルールのデータベースの場所にある現在のデータに対応するRuleDataSnapshotを提供します (データベースのルートのデータを提供する root とは対照的です)。

たとえば、 /users/<user>/public true に設定されている場合に、任意のクライアントが/users/<user> /<user> にアクセスできるようにしたい場合は、次のように使用できます。

{
  "rules": {
    "users": {
      "$user": {
        ".read": "data.child('public').val() == true"
      }
    }
  }
}

データ変数は.read.write 、および.validateルールで使用できます。

新しいデータ

書き込みが許可された場合に生成されるデータに対応するRuleDataSnapshot

.writeルールと.validateルールの場合、newData 変数は、書き込みが許可された場合に生成されるデータに対応するRuleDataSnapshotを提供します (これは、既存のデータと書き込まれる新しいデータの「マージ」です)。したがって、すべてのユーザーに名前と年齢があることを確認したい場合は、次のように使用できます。

{
  "rules": {
    "users": {
      "$user": {
        ".read": true,
        ".write": true,
        ".validate": "newData.hasChildren(['name', 'age'])"
      }
    }
  }
}

newData は既存のデータと新しいデータをマージするため、「部分的な」更新であっても適切に動作します。例えば:

var fredRef = firebase.database().ref("users/fred");
// Valid since we have a name and age.
fredRef.set({ name: "Fred", age: 19 });
// Valid since we are updating the name but there's already an age.
fredRef.child("age").set(27);
// Invalid since the .validate rule will no longer be true.
fredRef.child("name").remove();

新しいデータが書き込まれないため、newData 変数は.readルールでは使用できません。データのみを使用する必要があります。

RuleDataSnapshot: メソッド

val()

このRuleDataSnapshotからプリミティブ値 ( stringnumberboolean 、またはnull ) を取得します。

戻り値: ( StringNumberBooleanNull ) - このRuleDataSnapshotからのプリミティブ値。

DataSnapshot.val()とは異なり、子データを持つ RuleDataSnapshot でval()を呼び出しても、子を含むオブジェクトは返されません。代わりに、特別なセンチネル値を返します。これにより、ルールが常に非常に効率的に動作することが保証されます。

結果として、子にアクセスするには常にchild()を使用する必要があります (例: data.child('name').val() data.val().name ) )。

この例では、読み取られる場所で isReadable 子が true に設定されている場合にのみ読み取りを許可します。

".read": "data.child('isReadable').val() == true"

子供()

指定された相対パスの場所のRuleDataSnapshotを取得します。

引数: childPath String - 子データの場所への相対パス。

戻り値: RuleDataSnapshot - 子の場所のRuleDataSnapshot

相対パスは、単純な子の名前 (例: 'fred') またはより深いスラッシュで区切られたパス (例: 'fred/name/first') のいずれかです。子の場所にデータがない場合は、空の RuleDataSnapshot が返されます。

この例では、読み取られる場所で isReadable 子が true に設定されている場合にのみ読み取りを許可します。

".read": "data.child('isReadable').val() == true"

親()

親の場所のRuleDataSnapshotを取得します。

戻り値: RuleDataSnapshot - 親の場所のRuleDataSnapshot

このインスタンスが Firebase Realtime Database のルートを参照している場合、親が存在しないため、 parent()が失敗し、現在のルール式が(失敗として)スキップされます。

この例では、isReadable 兄弟が true に設定されている場合にのみ読み取りを許可します。

".read": "data.parent().child('isReadable').val() == true"

hasChild(childPath)

指定された子が存在する場合は true を返します。

引数: childPath String - 潜在的な子の場所への相対パス。

戻り値:ブール値 - 指定された子パスにデータが存在する場合はtrue 。それ以外の場合はfalse

この例では、データに子「名前」が含まれている場合にのみ、データの書き込みを許可します。

".validate": "newData.hasChild('name')"

hasChildren([子])

子供の存在を確認します。

引数: children Array (オプション) - すべて存在する必要がある子キーの配列。

戻り値: Boolean値 - (指定された) 子が存在する場合はtrue 。それ以外の場合はfalse

引数が指定されていない場合、 RuleDataSnapshotに子がある場合は true を返します。子名の配列が指定された場合、指定されたすべての子がRuleDataSnapshotに存在する場合にのみ true を返します。

この例では、データに 1 つ以上の子が含まれている場合にのみ、データの書き込みを許可します。

".validate": "newData.hasChildren()"

この例では、データに「name」と「age」の子が含まれる場合にのみ、データの書き込みを許可します。

".validate": "newData.hasChildren(['name', 'age'])"

存在します()

このRuleDataSnapshotにデータが含まれている場合は true を返します。

戻り値: Boolean値 - RuleDataSnapshotにデータが含まれている場合はtrue 。それ以外の場合はfalse

このRuleDataSnapshotにデータが含まれている場合、exists 関数は true を返します。 data.exists() data.val() != nullと同等であるため、これは純粋に便利な関数です。

この例では、既存のデータがない限り、この場所への書き込みが許可されます。

".write": "!data.exists()"

getPriority()

RuleDataSnapshot内のデータの優先度を取得します。

戻り値: ( StringNumberNull ) - このRuleDataSnapshot内のデータの優先順位。

この例では、書き込まれる新しいデータが優先されるようにします。

".validate": "newData.getPriority() != null"

isNumber()

このRuleDataSnapshotに数値が含まれている場合は true を返します。

戻り値: Boolean値 - データが数値の場合はtrue 。それ以外の場合はfalse

この例では、書き込まれる新しいデータに数値を持つ子「age」があることが保証されます。

".validate": "newData.child('age').isNumber()"

isString()

このRuleDataSnapshotに文字列値が含まれている場合は true を返します。

戻り値: Boolean値 - データがStringの場合はtrue 。それ以外の場合はfalse

この例では、書き込まれる新しいデータに文字列値を持つ子「name」があることが保証されます。

".validate": "newData.child('name').isString()

isBoolean()

このRuleDataSnapshotにブール値が含まれている場合は true を返します。

戻り値: Boolean値 - データがBooleanの場合はtrue 。それ以外の場合はfalse

この例では、書き込まれる新しいデータにブール値を持つ子「active」があることが保証されます。

".validate": "newData.child('active').isBoolean()"

文字列: プロパティ

長さ

文字列の長さを返します。

戻り値: Number - 文字列内の文字数。

この例では、文字列は少なくとも 10 文字である必要があります。

".validate": "newData.isString() && newData.val().length >= 10"

文字列: メソッド

含む(部分文字列)

文字列に指定された部分文字列が含まれる場合は true を返します。

引数: substring String - 検索する部分文字列。

戻り値: Boolean値 - 文字列に指定された部分文字列が含まれる場合はtrue 。それ以外の場合はfalse

この例では、データが「@」を含む文字列である必要があります。

".validate": "newData.isString() && newData.val().contains('@')"

で始まる(部分文字列)

文字列が指定された部分文字列で始まる場合は true を返します。

引数: substring String - 先頭で検索する部分文字列。

戻り値: Boolean値 - 文字列に指定された部分文字列が含まれる場合はtrue 。それ以外の場合はfalse

この例では、 auth.token.identifier 「internal-」で始まる場合に読み取りアクセスを許可します。

".read": "auth.token.identifier.beginsWith('internal-')"

で終わる(部分文字列)

文字列が指定された部分文字列で終わる場合は true を返します。

引数: substring String - 最後に検索する部分文字列。

戻り値: Boolean値 - 文字列が指定された部分文字列で終わる場合はtrue 。それ以外の場合はfalse

この例では、 auth.token.identifier 「@company.com」で終わる場合に読み取りアクセスを許可します。

".read": "auth.token.identifier.endsWith('@company.com')"

replace(部分文字列、置換)

指定された部分文字列のすべてのインスタンスが指定された置換文字列で置き換えられた文字列のコピーを返します。

引数: substring String - 検索する部分文字列。 replacement String - 部分文字列を置換する文字列。

戻り値: String - 部分文字列を置換で置換した後の新しい文字列。

replace()メソッドは、最初のインスタンスだけでなく、指定された部分文字列のすべてのインスタンスを指定された置換文字列に置き換えるという点で、JavaScript replace()メソッドとは少し異なります。

キーではピリオドを使用できないため、文字列を保存する前にピリオドを使用してエスケープする必要があります。この例としては、電子メール アドレスが挙げられます。 /whitelist/ノードにホワイトリストに登録された電子メール アドレスのリストがあると仮定します。

{
 "user": {
   "$uid": {
     "email": <email>
   }
 },
 "whitelist": {
   "fred@gmail%2Ecom": true,
   "barney@aol%2Ecom": true
 }
}

電子メールが/whitelist/ノードにある場合にのみユーザーの追加を許可するルールを作成できます。

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "true",
        ".write": "root.child('whitelist').child(newData.child('email').val().replace('.', '%2E')).exists()"
      }
    }
  }
}

toLowerCase()

小文字に変換された文字列のコピーを返します。

戻り値: String - 小文字に変換された文字列。

この例では、 auth.token.identifier (すべて小文字) が/usersの下に存在する場合に読み取りアクセスを許可します。

".read": "root.child('users').child(auth.token.identifier.toLowerCase()).exists()"

toUpperCase()

大文字に変換された文字列のコピーを返します。

戻り値: String - 大文字に変換された文字列。

この例では、すべて大文字のauth.token.identifier /usersの下に存在する場合、読み取りアクセスを許可します。

".read": "root.child('users').child(auth.token.identifier.toUpperCase()).exists()"

一致(正規表現)

文字列が指定された正規表現リテラルに一致する場合は true を返します。

戻り値: Boolean値 - 文字列が正規表現リテラル (regex) に一致する場合はtrue 。それ以外の場合はfalse

完全なルール正規表現ドキュメントを参照してください。

オペレーター

+(追加)

変数の追加または文字列の連結に使用されます。

次の例では、新しい値によって既存の値が 1 だけ増加することが保証されます。これはカウンターを実装する場合に便利です。

".write": "newData.val() === data.val() + 1"
".validate": "root.child('room_names/' + $room_id).exists()"

- (否定または減算)

ルール式で値を否定するか、2 つの値を減算するために使用されます。

この検証ルールは、新しい値がその場所の子の値の逆数であることを確認します。

".validate": "newData.val() === -(data.child('quantity').val())"

次の例では、減算を使用して、過去 10 分間のメッセージのみを読み取ることができるようにしています。

".read": "newData.child('timestamp').val() > (now - 600000)"

* (かける)

ルール式で変数を乗算するために使用されます。

この検証ルールは、新しい値が価格と数量の積 (2 つの既存の値) に等しいかどうかを確認します。

".validate": "newData.val() === data.child('price').val() * data.child('quantity').val()"

/ (分ける)

ルール式内の変数を分割するために使用されます。

次の例では、検証ルールにより、保存されたデータが他の場所に保存された合計データの平均であることが確認されます。

".validate": "newData.val() === data.parent().child('sum').val() / data.parent().child('numItems').val()"

% (係数)

ルール式で、ある変数を別の変数で除算した余りを求めるために使用されます。

このルールは、偶数のみを書き込めることを検証します。

".validate": "newData.val() % 2 === 0"

=== (等しい)

ルール式内の 2 つの変数の型と値が同じかどうかを確認するために使用されます。

次のルールでは、=== 演算子を使用して、ユーザー アカウントの所有者のみに書き込みアクセスを許可します。ルールが true と評価されるには、ユーザーの uid がキー ( $user_id ) と正確に一致する必要があります。

"users": {
  ".write": "$user_id === auth.uid"
}

!== (等しくない)

ルール式内の 2 つの変数が等しくないかどうかをチェックするために使用されます。

次の読み取りルールにより、ログインしたユーザーのみがデータを読み取ることができます。

".read": "auth !== null"

&& (そして)

両方のオペランドが true の場合、true と評価されます。ルール式内の複数の条件を評価するために使用されます。

次の検証ルールは、新しいデータが 100 文字未満の文字列であることをチェックします。

".validate": "newData.isString() && newData.val().length < 100"

|| (または)

ルール式内の 1 つのオペランドが true の場合、true と評価されます。

この例では、古いデータまたは新しいデータが存在しない限り書き込み可能です。つまり、データを削除または作成する場合は書き込みできますが、データを更新する場合は書き込みできません。

".write": "!data.exists() || !newData.exists()"

! (ない)

単一のオペランドが false の場合、true と評価されます。ルール式では、!演算子は、データが特定の場所に書き込まれたかどうかを確認するためによく使用されます。

次のルールでは、指定された場所にデータがない場合にのみ書き込みアクセスが許可されます。

".write": "!data.exists()"

> (より大きい)

ルール式内の値が別の値より大きいかどうかをチェックするために使用されます。

この検証ルールは、書き込まれる文字列が空の文字列ではないことをチェックします。

".validate": "newData.isString() && newData.val().length > 0"

< (未満)

ルール式内の値が別の値より小さいかどうかをチェックするために使用されます。

この検証ルールは、文字列が 20 文字未満であることをチェックします。

".validate": "newData.isString() && newData.val().length < 20"

>= (以上)

ルール式内の値が別の値以上であるかどうかをチェックするために使用されます。

この検証ルールは、書き込まれる文字列が空の文字列ではないことをチェックします。

".validate": "newData.isString() && newData.val().length >= 1"

<= (以下)

ルール式内の値が別の値以下であるかどうかをチェックするために使用されます。

この検証ルールにより、今後新しいデータを追加できないことが保証されます。

".validate": "newData.val() <= now"

? (三項演算子)

条件付きルール式を評価するために使用されます。

三項演算子は 3 つのオペランドを取ります。 ? の前のオペランドが条件です。条件が true と評価されると、2 番目のオペランドが評価されます。条件が false の場合、3 番目のオペランドが評価されます。

次の検証ルールの場合、新しい値は数値またはブール値になります。数値の場合は、0 より大きくなければなりません。

".validate": "newData.isNumber() ? newData.val() > 0 : newData.isBoolean()"