Firebase Database Security Rules API

ルール: タイプ

.read

Firebase Realtime Database のロケーションへの読み取りアクセス権をクライアントに付与します。

.read ルールはセキュリティ ルールの一種で、Firebase Realtime Database のロケーションへの読み取りアクセス権をクライアントに付与します。例:

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

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

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

.write

Firebase Realtime Database のロケーションへの書き込みアクセス権をクライアントに付与します。

.write ルールはセキュリティ ルールの一種で、Firebase Realtime Database の場所への書き込みアクセス権をクライアントに付与します。例:

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

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

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

.validate

.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 ルールについて詳しくは、セキュリティ ガイドのデータのインデックス登録に関するセクションをご覧ください。

ルール: 変数

auth

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

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

フィールド 説明
provider 使用された認証方法(「password」、「anonymous」、「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'"
    }
  }
}

auth.token

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

root

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 ノードに書き込むことができます。

データ

RuleDataSnapshot。現在実行中のルールの場所にある Firebase Realtime Database の現在のデータに対応しています。

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

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

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

データ変数は .read.write.validate 個のルール。

newData

書き込みが許可された場合に生成されるデータに対応する 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();

書き込まれる新しいデータがないため、.read ルールでは newData 変数を使用できません。データを使うだけです。

RuleDataSnapshot: メソッド

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

戻り値: (String, Number, Boolean, Null) - この RuleDataSnapshot のプリミティブ値。

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

そのため、子にアクセスするには、常に child() を使用する必要があります(例: data.val().name ではなく data.child('name').val())。

この例では、読み取る場所で 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 sibling が true に設定されている場合にのみ読み取りが許可されます。

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

hasChild(childPath)

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

引数: childPath String - 子候補の場所への相対パス。

戻り値: ブール値 - 指定された子パスにデータが存在する場合は true。でなければ false です。

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

".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'])"

is()

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

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

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

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

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

getPriority()

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

戻り値: (String, Number, Null) - この 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

この例では、書き込まれる新しいデータに子「アクティブ」が含まれることを保証します。渡します。

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

文字列: プロパティ

長さ

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

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

この例では、文字列は 10 文字以上である必要があります。

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

文字列: メソッド

contains(部分文字列)

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

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

戻り値: Boolean - 文字列に指定された部分文字列が含まれている場合は true。そうでない場合は false

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

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

startedWith(部分文字列)

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

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

戻り値: Boolean - 文字列に指定された部分文字列が含まれている場合は true。そうでない場合は false

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

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

endWith(部分文字列)

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

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

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

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

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

置換(部分文字列, 置換)

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

引数: 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 - 小文字に変換された文字列。

この例では、すべて小文字が /users の下にあるため、auth.token.identifier の場合に読み取りアクセスが許可されます。

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

&&(AND)

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

次の検証ルールは、新しいデータが 100 文字未満の文字列かどうかを確認します。

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

||(または)

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

この例では、古いデータまたは新しいデータが存在しない限り書き込むことができます。言い換えれば、データの削除や作成はできても、データの更新は行わない場合は書き込むことができます。

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

!(NOT)

単一のオペランドが 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 項演算子)

条件ルール式の評価に使用されます。

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

次の検証ルールでは、新しい値は数値またはブール値です。数値の場合は 0 より大きくする必要があります。

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