---
title: "Firebase security rules piemēri: 11 izmēģināti noteikumi"
description: "Firebase security rules piemēri, izmēģināti emulatorā. Ko katrs noteikums ļāva viesim vai citam lietotājam, kādas noplūdes palika un kurš noteikums tās aizvēra."
url: "https://madsalt.tech/lv/blog/firebase-security-rules-examples/"
author: "Denys Zaichenko"
author_url: "https://madsalt.tech/lv/about/"
language: "lv"
published: 2026-11-03
---

# Firebase security rules piemēri: 11 izmēģināti noteikumi

Īsumā

Es nosūtīju vienus un tos pašus pieprasījumus pret 11 Firestore noteikumu kopām kā viesis, anonīms lietotājs un trīs pieteikušies lietotāji. `request.auth != null` ļāva svešiniekam lasīt, mainīt un dzēst visu pasūtījumus. Īpašnieka pārbaude tikai pēc `resource` ļāva lietotājam nodot pasūtījumu citam. Viens plašs `{document=**}` match atvēra kolekciju, kurai bija pareizs īpašnieka noteikums. Un loma, kas glabājas dokumentā, ko lietotājs drīkst rakstīt, padarīja viņu par administratoru ar vienu pieprasījumu. Katram gadījumam zemāk ir labojums, un labotais noteikums izturēja tos pašus pieprasījumus.

Starp pārlūku un datubāzi Firebase lietotnē nav jūsu servera. Projekta konfigurācija nāk līdzi lapai, un [security rules](https://firebase.google.com/docs/rules/insecure-rules) ir vienīgais, kas stāv starp ikvienu, kam tā ir, un jūsu datiem. Tāpēc es gribēju piemērus, kuros blakus noteikumam ir uzbrukums, nevis sarakstu ar noteikumiem, kas tikai izskatās pareizi.

**Kā testēju.** Firebase Local Emulator Suite no Firebase CLI 15.34.2, 2026. gada 3. novembrī. Katru noteikumu kopu ielādēju, atiestatīju datus un izsaucu Firestore REST API ar īstiem tokeniem no Auth emulatora: bez tokena, anonīms lietotājs, lietotāji A un B un svešinieks, kas tikai reģistrējies. Dati izdomāti: pasūtījumi `a1` un `a2` pieder A, `b1` pieder B.

## Kuri Firebase noteikumi laiž cauri?

| Noteikums                                       | Pieprasījums                               | Rezultāts     |
| ----------------------------------------------- | ------------------------------------------ | ------------- |
| `if true` (testa režīms)                        | Viesis izgūst pasūtījumu sarakstu          | `200`, visi 3 |
| `if true` (testa režīms)                        | Viesis dzēš B pasūtījumu                   | `200`         |
| `request.auth != null`                          | Anonīms lietotājs izgūst sarakstu          | `200`, visi 3 |
| `request.auth != null`                          | Svešinieks dzēš A pasūtījumu               | `200`         |
| Īpašnieka pārbaude tikai pēc `resource`         | A izveido pasūtījumu, kas pieder B         | `200`         |
| Īpašnieka pārbaude tikai pēc `resource`         | A maina sava pasūtījuma `ownerId`          | `200`         |
| Īpašnieka noteikums plus `{document=**}` read   | A lasa B pasūtījumu                        | `200`         |
| Lietotājs drīkst rakstīt savu `users` dokumentu | A iestata `role: admin`, lasa B pasūtījumu | `200`         |

## Ko īsti atver testa režīms?

```
match /{document=**} {
  allow read, write: if true;
}
```

Visu, ikvienam. Viesis bez tokena izgūva visus 3 pasūtījumus, vienu izdzēsa un izveidoja jaunu. Tam nevajag ne konta, ne noplūdušu noslēpumu, tikai projekta id.

Datētajai testa režīma versijai ir cita kļūme. Ar `if request.time < timestamp.date(2026, 1, 1)` un šo datumu pagātnē viesis saņēma `403`, un tāpat lietotājs A, lasot savu pasūtījumu. Noplūde beidzās, un kopā ar to arī lietotne.

## Vai ar `request.auth != null` pietiek?

Nē. Tas tikai saka, ka aiz pieprasījuma ir kāds konts.

```
match /orders/{id} {
  allow read, write: if request.auth != null;
}
```

Viesis saņēma `403`, tāpēc šis noteikums šķiet drošs ātrā testā. Tad svešinieks, kas tikai reģistrējies, izgūva visus 3 pasūtījumus, nomainīja B pasūtījuma summu un izdzēsa A pasūtījumu, katru reizi ar `200`. Anonīms lietotājs arī izgūva visus 3. Ja reģistrācija ir atvērta, šis noteikums nozīmē „ikviens, kas pasteidzas reģistrēties”. Firebase dokumentācija to arī min kā [bieži sastopamu nedrošu paraugu](https://firebase.google.com/docs/rules/insecure-rules).

## Kāpēc īpašnieka pārbaudei vajag gan `resource`, gan `request.resource`?

`resource` ir dokuments, kāds tas glabājas. `request.resource` ir dokuments, kāds tas kļūtu pēc ieraksta. Noteikums, kas skatās tikai uz pirmo, pārbauda, kam rinda pieder tagad, un neko nesaka par to, par ko to pārvērš.

```
match /orders/{id} {
  allow read, update, delete: if resource.data.ownerId == request.auth.uid;
  allow create: if request.auth != null;
}
```

Lasīšana izskatījās pareizi: A saņēma `200` uz savu pasūtījumu un `403` uz B pasūtījumu. Rakstīšana nē. A izveidoja jaunu pasūtījumu ar `ownerId`, kas iestatīts uz B, un saņēma `200`. Tad A nomainīja sava pasūtījuma `ownerId` uz B, arī `200`, un B no tā brīža to varēja lasīt. Lietotnē, kur pasūtījumi nozīmē rēķinus vai atlikumus, tā ir lietotāja rakstīšana svešā kontā.

Šī versija noraidīja visu:

```
match /orders/{id} {
  allow read, delete: if request.auth != null
    && resource.data.ownerId == request.auth.uid;
  allow create: if request.auth != null
    && request.resource.data.ownerId == request.auth.uid;
  allow update: if request.auth != null
    && resource.data.ownerId == request.auth.uid
    && request.resource.data.ownerId == resource.data.ownerId;
}
```

| A pieprasījums                    | Rezultāts |
| --------------------------------- | --------- |
| Lasīt savu pasūtījumu             | `200`     |
| Lasīt, mainīt, dzēst B pasūtījumu | `403`     |
| Izveidot pasūtījumu, kas pieder B | `403`     |
| Mainīt `ownerId` uz B             | `403`     |

Tomēr A varēja nomainīt `total` savam pasūtījumam, ar `200`. Ja klients nedrīkst iestatīt šo lauku, nosauciet laukus, ko drīkst mainīt:

```
allow update: if request.auth != null
  && resource.data.ownerId == request.auth.uid
  && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['note']);
```

Ar to `total` maiņa atgrieza `403`, bet `note` maiņa atgrieza `200`.

## Kāpēc mans vaicājums neizdevās ar pareizu noteikumu?

Tāpēc, ka [noteikumi nav filtri](https://firebase.google.com/docs/firestore/security/rules-query). Pie iepriekš minētā īpašnieka noteikuma A, pieprasot visu kolekciju, saņēma `403`, lai gan A pieder 2 no 3 pasūtījumiem. Firestore vērtē vaicājumu pēc tā, ko tas varētu atgriezt, nevis pēc tā, kas tur ir.

| A pieprasījums           | Rezultāts     |
| ------------------------ | ------------- |
| Izgūt visus pasūtījumus  | `403`         |
| Vaicājums `ownerId == A` | `200`, 2 dok. |
| Vaicājums `ownerId == B` | `403`         |

Tāpēc, ja saraksts salūst pēc noteikumu pastiprināšanas, labojiet vaicājumu. Noteikuma atslābināšana, lai saraksts strādātu, ir tieši tas, kā tiek uzrakstīti iepriekš minētie plašie noteikumi.

## Vai plašs match var atcelt pareizu noteikumu?

Jā, un tieši to es vispirms meklētu projektā ar garu noteikumu failu. Firestore [atļauj pieprasījumu, ja to atļauj kāds no atbilstošajiem noteikumiem](https://firebase.google.com/docs/firestore/security/rules-structure).

```
match /orders/{id} {
  allow read: if request.auth != null
    && resource.data.ownerId == request.auth.uid;
}
match /{document=**} {
  allow read: if request.auth != null;
}
```

Pirmais bloks izskatās pēc laba īpašnieka noteikuma. Kad otrais bloks ir klāt, A izlasīja B pasūtījumu ar `200`, svešinieks izgūva visus 3 pasūtījumus, un tas pats svešinieks izlasīja A dokumentu kolekcijā `users`. Pirmajā blokā nekas nebrīdina. Izdzēsiet plašo match; veida, kā ar vēlāku noteikumu atņemt piekļuvi, nav.

## Kā lietotājs pats sevi padara par administratoru?

Šis paraugs parādās ikreiz, kad lomas glabājas dokumentā:

```
function isAdmin() {
  return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
}
match /users/{uid} {
  allow read, write: if request.auth.uid == uid;
}
match /orders/{id} {
  allow read: if resource.data.ownerId == request.auth.uid || isAdmin();
}
```

„Lietotāji var rediģēt savu profilu” un „administratori var lasīt visus pasūtījumus” katrs atsevišķi ir saprātīgs. Kopā tā ir privilēģiju eskalācija.

![Administrators ar vienu pieprasījumu. Lietotājs A, kura paša users dokumentu var rakstīt. Pirms: Lietotājs A → lasa B pasūtījumu → 403; Ierakstīt lomu: Lietotājs A → role: admin → 200; Pēc: Lietotājs A → lasa B pasūtījumu → 200.](https://madsalt.tech/charts/lv/firebase-security-rules-examples.svg)

*1. att. Mans tests Firebase emulatorā (CLI 15.34.2), 2026. gada 3. novembris.*

Labojums ir neļaut klientam rakstīt šo lauku. Pievienojot rakstīšanas noteikumam `request.resource.data.role == resource.data.role`, tas pats pieprasījums atgrieza `403`, un A palika ārpus B pasūtījuma. Otrs veids ir custom claims, ko iestata no servera, jo klients tos nevar mainīt.

## Divas lietas, kas izrādījās kārtībā

Vecāka noteikumi neiesūcas apakškolekcijās. Ar `allow read` uz `/orders/{id}` jebkuram pieteikušamies lietotājam A izlasīja pasūtījumu, bet `/orders/b1/notes/n1` zem tā atgrieza `403`. Tā ir [dokumentētā uzvedība](https://firebase.google.com/docs/firestore/security/rules-structure): noteikumi attiecas tikai uz atbilstošo ceļu.

Viesis neizlien cauri salīdzinājumam ar trūkstošu tokenu. `resource.data.ownerId == request.auth.uid` viesim atgrieza `403` pat bez atsevišķa `request.auth != null`. Es tomēr šo pārbaudi uzrakstu, jo tad noteikums saka to, ko tas nozīmē.

## Kā pārbaudīt savus noteikumus?

Palaidiet savus pieprasījumus emulatorā kā viesis, kā svešinieks un kā otrs lietotājs. Tieši tā atklājās katrs iepriekš minētais gadījums; noteikumu lasīšana to neatklāja.

Pirmajam piegājienam bezmaksas [Firebase noteikumu pārbaude](https://madsalt.tech/lv/tools/firebase-rules-checker/) nolasa ielīmētus noteikumus, nepieskaroties jūsu projektam. Šeit minētajās kopās tā atzīmēja testa režīmu, piekļuvi tikai pieteikušamies, plašo match un paša rakstīto lomu. Tā lasa tikai tekstu, tāpēc nevar pateikt, kā izskatās jūsu dati un vai noteikums tika izvietots.

Jūsu `apiKey` lapā pats par sevi nav problēma. Firebase web konfigurācija pēc dizaina ir publiska, un bezmaksas [Noslēpumu skeneris](https://madsalt.tech/lv/tools/secret-scanner/) to tā arī atzīmē, jo datus aiz tās aizsargā noteikumi. Failiem ir citi noteikumi un noplūde, ko noteikumi apturēt nevar, un to es pārbaudīju rakstā Firebase Storage rules.

**Ierobežojumi.** Tikai Firestore, lokālā emulatorā, caur REST, ar izdomātiem datiem. Realtime Database izmanto citu noteikumu valodu un netika testēta. App Check, kas ierobežo, kuras lietotnes drīkst izsaukt jūsu backend, šeit nav iekļauts; tas noteikumus neaizstāj. Produkcijā detaļas var atšķirties no emulatora, un to es nepārbaudīju.

Neesat pārliecināts, ko jūsu noteikumi laiž cauri?

Labprāt izlasīšu tos kopā ar jums. Bez pārdošanas sarunas.

[Sazināties](https://madsalt.tech/lv/#contact)
