---
title: "Firebase security rules pavyzdžiai: 11 išbandytų taisyklių"
description: "Firebase security rules pavyzdžiai, išbandyti emuliatoriuje. Ką taisyklė leido svečiui ar kitam vartotojui, kas liko atvira ir kuri taisyklė tai uždarė."
url: "https://madsalt.tech/lt/blog/firebase-security-rules-examples/"
author: "Denys Zaichenko"
author_url: "https://madsalt.tech/lt/about/"
language: "lt"
published: 2026-11-03
---

# Firebase security rules pavyzdžiai: 11 išbandytų taisyklių

Trumpai

Tas pačias užklausas išsiunčiau prieš 11 Firestore taisyklių rinkinių kaip svečias, anoniminis vartotojas ir trys prisijungę vartotojai. `request.auth != null` leido pašaliniam žmogui skaityti, keisti ir trinti visų užsakymus. Savininko patikra tik pagal `resource` leido vartotojui perduoti užsakymą kitam. Vienas platus `{document=**}` match atvėrė kolekciją, kuri turėjo teisingą savininko taisyklę. O rolė, laikoma vartotojo įrašomame dokumente, vienu užklausimu padarė jį administratoriumi. Kiekvienam atvejui žemiau yra pataisymas, ir pataisyta taisyklė atlaikė tas pačias užklausas.

Tarp naršyklės ir duomenų bazės Firebase programoje nėra jūsų serverio. Projekto konfigūracija pateikiama kartu su puslapiu, o [security rules](https://firebase.google.com/docs/rules/insecure-rules) yra vienintelis barjeras tarp bet kurio jos turėtojo ir jūsų duomenų. Todėl norėjau pavyzdžių, kuriuose šalia taisyklės parodyta ataka, o ne sąrašo taisyklių, kurios tik atrodo teisingos.

**Kaip testavau.** Firebase Local Emulator Suite iš Firebase CLI 15.34.2, 2026 m. lapkričio 3 d. Kiekvieną taisyklių rinkinį įkėliau, atstačiau duomenis ir kviečiau Firestore REST API su tikrais Auth emuliatoriaus tokenais: be tokeno, anoniminis vartotojas, vartotojai A ir B bei pašalinis, kuris tik užsiregistravo. Duomenys išgalvoti: užsakymai `a1` ir `a2` priklauso A, `b1` priklauso B.

## Kurios Firebase taisyklės praleidžia?

| Taisyklė                                      | Užklausa                                   | Rezultatas    |
| --------------------------------------------- | ------------------------------------------ | ------------- |
| `if true` (testavimo režimas)                 | Svečias išvardija užsakymus                | `200`, visi 3 |
| `if true` (testavimo režimas)                 | Svečias ištrina B užsakymą                 | `200`         |
| `request.auth != null`                        | Anoniminis vartotojas išvardija užsakymus  | `200`, visi 3 |
| `request.auth != null`                        | Pašalinis ištrina A užsakymą               | `200`         |
| Savininko patikra tik pagal `resource`        | A sukuria užsakymą, priklausantį B         | `200`         |
| Savininko patikra tik pagal `resource`        | A pakeičia savo užsakymo `ownerId`         | `200`         |
| Savininko taisyklė ir `{document=**}` read    | A skaito B užsakymą                        | `200`         |
| Vartotojas gali rašyti savo `users` dokumentą | A nustato `role: admin`, skaito B užsakymą | `200`         |

## Ką iš tikrųjų atveria testavimo režimas?

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

Viską ir visiems. Svečias be tokeno išvardijo visus 3 užsakymus, vieną ištrynė ir sukūrė naują. Tam nereikia nei paskyros, nei nutekėjusios paslapties, tik projekto id.

Datuota testavimo režimo versija suklysta kitaip. Su `if request.time < timestamp.date(2026, 1, 1)` ir šia data praeityje svečias gavo `403`, o vartotojas A, skaitantis savo užsakymą, taip pat. Nutekėjimas baigėsi, bet kartu ir programa.

## Ar pakanka `request.auth != null`?

Ne. Ji tik sako, kad už užklausos yra kokia nors paskyra.

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

Svečias gavo `403`, todėl per greitą testą ši taisyklė atrodo saugi. Tada pašalinis, kuris tik užsiregistravo, išvardijo visus 3 užsakymus, pakeitė B užsakymo sumą ir ištrynė A užsakymą, visais atvejais su `200`. Anoniminis vartotojas taip pat išvardijo visus 3. Jei registracija atvira, ši taisyklė reiškia „visi, kas nepatingi užsiregistruoti“. Firebase dokumentacija ją irgi laiko [įprastu nesaugiu šablonu](https://firebase.google.com/docs/rules/insecure-rules).

## Kodėl savininko patikrai reikia ir `resource`, ir `request.resource`?

`resource` yra dokumentas, koks jis saugomas. `request.resource` yra dokumentas, koks jis taptų po rašymo. Taisyklė, žiūrinti tik į pirmąjį, tikrina, kam eilutė priklauso dabar, bet nieko nesako apie tai, kuo ją paverčia.

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

Skaitymas atrodė teisingai: A gavo `200` savo užsakymui ir `403` B užsakymui. Rašymas ne. A sukūrė naują užsakymą su `ownerId`, nustatytu į B, ir gavo `200`. Tada A pakeitė savo užsakymo `ownerId` į B, taip pat `200`, ir nuo to laiko B galėjo jį skaityti. Programoje, kur užsakymai reiškia sąskaitas ar likučius, tai yra vartotojas, rašantis į svetimą paskyrą.

Ši versija atmetė viską:

```
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 užklausa                          | Rezultatas |
| ----------------------------------- | ---------- |
| Skaityti savo užsakymą              | `200`      |
| Skaityti, keisti, trinti B užsakymą | `403`      |
| Sukurti užsakymą, priklausantį B    | `403`      |
| Pakeisti `ownerId` į B              | `403`      |

Vis tiek A galėjo pakeisti `total` savo užsakyme, su `200`. Jei klientas šio lauko nustatinėti negali, nurodykite, kuriuos laukus jam leidžiama keisti:

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

Su ja `total` keitimas grąžino `403`, o `note` keitimas grąžino `200`.

## Kodėl mano užklausa nepavyko su teisinga taisykle?

Nes [taisyklės nėra filtrai](https://firebase.google.com/docs/firestore/security/rules-query). Pagal aukščiau pateiktą savininko taisyklę A, paprašęs visos kolekcijos, gavo `403`, nors A priklauso 2 iš 3 užsakymų. Firestore vertina užklausą pagal tai, ką ji galėtų grąžinti, o ne pagal tai, kas yra.

| A užklausa                | Rezultatas    |
| ------------------------- | ------------- |
| Išvardyti visus užsakymus | `403`         |
| Užklausa `ownerId == A`   | `200`, 2 dok. |
| Užklausa `ownerId == B`   | `403`         |

Taigi, kai sąrašas suluošėja sugriežtinus taisykles, taisykite užklausą. Taisyklės atlaisvinimas, kad sąrašas veiktų, yra būtent tas būdas, kuriuo parašomos aukščiau aprašytos plačios taisyklės.

## Ar platus match gali panaikinti teisingą taisyklę?

Taip, ir to aš pirmiausia ieškočiau projekte su ilgu taisyklių failu. Firestore [leidžia užklausą, jei ją leidžia bet kuri atitinkanti taisyklė](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;
}
```

Pirmasis blokas atrodo kaip gera savininko taisyklė. Esant antrajam blokui A perskaitė B užsakymą su `200`, pašalinis išvardijo visus 3 užsakymus, o tas pats pašalinis perskaitė A dokumentą `users`. Pirmajame bloke nėra nieko, kas perspėtų. Ištrinkite platųjį match; vėlesne taisykle prieigos atimti neįmanoma.

## Kaip vartotojas pats save padaro administratoriumi?

Šis šablonas atsiranda, kai tik rolės laikomos dokumente:

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

„Vartotojai gali redaguoti savo profilį“ ir „administratoriai gali skaityti visus užsakymus“ po atskirai yra pagrįsta. Kartu tai yra teisių eskalavimas.

![Administratorius per vieną užklausą. Vartotojas A, kurio paties users dokumentas įrašomas. Prieš: Vartotojas A → skaito B užsakymą → 403; Rolės įrašymas: Vartotojas A → role: admin → 200; Po: Vartotojas A → skaito B užsakymą → 200.](https://madsalt.tech/charts/lt/firebase-security-rules-examples.svg)

*1 pav. Mano testas Firebase emuliatoriuje (CLI 15.34.2), 2026 m. lapkričio 3 d.*

Pataisymas: neleisti klientui rašyti to lauko. Pridėjus `request.resource.data.role == resource.data.role` prie rašymo taisyklės, ta pati užklausa grąžino `403`, o A liko už B užsakymo ribų. Kitas būdas yra custom claims, nustatomi iš serverio, nes klientas jų pakeisti negali.

## Du dalykai, kurie pasirodė gerai

Tėvinio dokumento taisyklės neprasisunkia į subkolekcijas. Su `allow read` ant `/orders/{id}` bet kuriam prisijungusiam vartotojui A perskaitė užsakymą, o `/orders/b1/notes/n1` po juo grąžino `403`. Tai [dokumentuotas elgesys](https://firebase.google.com/docs/firestore/security/rules-structure): taisyklės taikomos tik atitikusiam keliui.

Svečias neprasmunka per palyginimą su trūkstamu tokenu. `resource.data.ownerId == request.auth.uid` svečiui grąžino `403` net be atskiro `request.auth != null`. Vis tiek šią patikrą užrašau, nes tada taisyklė sako tai, ką turi omenyje.

## Kaip patikrinti savo taisykles?

Vykdykite savo užklausas emuliatoriuje kaip svečias, kaip pašalinis ir kaip antras vartotojas. Būtent taip išaiškėjo kiekvienas aukščiau aprašytas atvejis; skaitant taisykles jų nepastebėjau.

Pirmam praėjimui nemokamas [Firebase taisyklių patikra](https://madsalt.tech/lt/tools/firebase-rules-checker/) skaito įklijuotas taisykles ir neliečia jūsų projekto. Čia pateiktuose rinkiniuose jis pažymėjo testavimo režimą, prieigą tik prisijungusiems, platųjį match ir pačių įrašomą rolę. Jis skaito tik tekstą, todėl negali pasakyti, kaip atrodo jūsų duomenys ar ar taisyklė buvo įdiegta.

Jūsų `apiKey` puslapyje pats savaime nėra problema. Firebase web konfigūracija pagal paskirtį yra vieša, o nemokamas [Paslapčių skeneris](https://madsalt.tech/lt/tools/secret-scanner/) ją taip ir pažymi, nes duomenis už jos saugo taisyklės. Failams galioja kitos taisyklės, su nutekėjimu, kurio taisyklės sustabdyti negali, ir tai išbandžiau straipsnyje Firebase Storage rules.

**Apribojimai.** Tik Firestore, vietiniame emuliatoriuje, per REST, su išgalvotais duomenimis. Realtime Database naudoja kitą taisyklių kalbą ir netestuota. App Check, ribojantis, kurios programos gali kreiptis į jūsų backend, čia neįtrauktas; jis taisyklių nepakeičia. Gamyboje detalės gali skirtis nuo emuliatoriaus, ir to netikrinau.

Nesate tikri, ką jūsų taisyklės praleidžia?

Mielai perskaitysiu jas kartu su jumis. Be pardavimų kalbų.

[Susisiekti](https://madsalt.tech/lt/#contact)
