Jak dodać kontrolę dostępu opartą na rolach (RBAC) do aplikacji
Aby dodać kontrolę dostępu opartą na rolach, przypisz każdemu użytkownikowi jedną lub więcej ról (np. administrator, edytor, przeglądający), określ, jakie działania może wykonywać każda rola, i sprawdzaj te uprawnienia na serwerze przy każdym żądaniu — nie tylko przez ukrywanie przycisków. Sprawdź też, czy rekord, do którego ktoś sięga, należy do konta lub zespołu użytkownika. Zacznij od kilku stałych ról w bazie danych i testuj, próbując bezpośrednio dotrzeć do cudzych danych.
Uwierzytelnianie a autoryzacja
Dwa pojęcia, które często się myli:
- Uwierzytelnianie to kim jesteś? — logowanie. Zobacz jak dodać logowanie do aplikacji.
- Autoryzacja to co możesz robić? — do jakich stron, rekordów i działań zalogowany użytkownik ma dostęp.
RBAC to najczęstszy sposób realizacji autoryzacji. Ma to znaczenie: według stanu na wrzesień 2026 Broken Access Control zajmuje pierwsze miejsce w OWASP Top 10:2025, powszechnie używanej liście najpoważniejszych zagrożeń bezpieczeństwa aplikacji webowych. Typowe błędy to użytkownicy czytający cudze rekordy przez zmianę ID w adresie URL albo zwykli użytkownicy wywołujący trasy API dostępne tylko dla administratorów.
Wybierz model
| Model | Jak działa | Dobre do | Kompromis |
|---|---|---|---|
| Pojedyncza kolumna roli | users.role = admin / member | Małe aplikacje z dwiema lub trzema rolami | Robi się bałagan, gdy ktoś potrzebuje różnych ról w różnych miejscach |
| Role i uprawnienia | Role przypisane do nazwanych uprawnień (invoices.approve); kod sprawdza uprawnienia | Aplikacje, których zasady będą rosnąć | Więcej tabel; lista uprawnień do utrzymania |
| Role w obrębie zespołu (multi-tenant) | Tabela członkostw: użytkownik + organizacja + rola | SaaS, w którym ludzie należą do zespołów lub przestrzeni roboczych | Każde zapytanie musi być ograniczone do organizacji |
| Oparte na atrybutach lub relacjach | Reguły dotyczące atrybutów rekordu („autor może edytować swój wpis”) lub relacji (udostępniono komuś) | Dokumenty, udostępnianie, złożone procesy | Trudniejsze do ogarnięcia; rozważ dedykowaną bibliotekę lub usługę |
| Role z dostawcy logowania | Twój dostawca logowania przechowuje role lub przynależność do organizacji | Aplikacje, które już korzystają z hostowanego dostawcy uwierzytelniania | Związane z tym dostawcą; nadal egzekwuj na swoim serwerze |
W praktyce większość aplikacji łączy dwie rzeczy: role określające, jakiego rodzaju działania ktoś może wykonać, oraz własność określającą, na których rekordach może je wykonać. „Edytorzy mogą edytować wpisy” to reguła roli; „…wpisy w ich własnej przestrzeni roboczej” to reguła własności. Potrzebujesz obu.
Zacznij prościej, niż Ci się wydaje. Administrator, członek i przeglądający wystarczy w zaskakująco wielu aplikacjach. Łatwiej później podzielić jedną rolę, niż rozplątać dziesięć ról, których nikt nie rozumie.
Zaprojektuj role przed napisaniem kodu
Najpierw spisz tabelę uprawnień prostym językiem. Pełni ona rolę specyfikacji dla AI i planu testów:
| Działanie | Właściciel | Administrator | Członek | Przeglądający |
|---|---|---|---|---|
| Przeglądanie projektów w zespole | ✓ | ✓ | ✓ | ✓ |
| Tworzenie i edycja projektów | ✓ | ✓ | ✓ | |
| Usuwanie projektów | ✓ | ✓ | ||
| Zapraszanie i usuwanie osób | ✓ | ✓ | ||
| Zmiana ról | ✓ | |||
| Rozliczenia | ✓ |
Rozstrzygnij też przypadki brzegowe: czy ostatni właściciel może odejść? Czy administrator może usunąć właściciela? Co widzi usunięty użytkownik?
Krok po kroku
1. Najpierw działające logowanie
RBAC działa na bazie uwierzytelniania. Serwer musi niezawodnie wiedzieć, kto wysyła każde żądanie — z sesji lub zweryfikowanego tokenu — a nigdy z ID użytkownika przesłanego przez przeglądarkę w treści żądania.
2. Przechowuj role w bazie danych
W aplikacji dla jednego zespołu wystarczy kolumna role w tabeli użytkowników. Dla zespołów użyj tabeli członkostw:
create table memberships (
user_id uuid references users(id),
organization_id uuid references organizations(id),
role text not null check (role in ('owner','admin','member','viewer')),
primary key (user_id, organization_id)
);
Nigdy nie pozwalaj użytkownikom ustawiać własnej roli zwykłą aktualizacją profilu. Zmiany ról przechodzą przez osobny endpoint, który sprawdza uprawnienia.
3. Sprawdzaj uprawnienia na serwerze, w jednym miejscu
Napisz jedną funkcję pomocniczą — coś w rodzaju can(user, 'projects.delete', project) — i wywołuj ją w każdej trasie API, akcji serwerowej i zadaniu w tle, które odczytuje lub zmienia dane. Jedna centralna funkcja łatwiej przejrzeć i przetestować niż sprawdzenia rozproszone po kodzie. Domyślnie odmawiaj: jeśli żadna reguła nie zezwala na działanie, zostaje ono zablokowane.
4. Ograniczaj każde zapytanie
Każde zapytanie o dane zespołu powinno uwzględniać zespół: where organization_id = :currentOrg, a nie tylko where id = :id. To powstrzymuje kogoś przed zmianą /projects/123 na /projects/124 i zobaczeniem projektu innej firmy. Dla rekordów z innych zespołów zwracaj „nie znaleziono” zamiast „brak dostępu”, żeby nie zdradzać, że istnieją.
5. Dodaj ochronę na poziomie bazy tam, gdzie to ma znaczenie
Row-level security (RLS) w Postgresie pozwala bazie wymuszać, jakie wiersze każdy użytkownik widzi. Jest niezbędne, jeśli przeglądarka rozmawia z bazą bezpośrednio (jak w niektórych hostowanych backendach), a w pozostałych przypadkach stanowi użyteczną drugą warstwę dla wrażliwych tabel.
6. Odzwierciedl role w interfejsie
Teraz ukryj lub wyłącz to, czego użytkownicy nie mogą zrobić, aby aplikacja nie wprowadzała w błąd. To tylko dla wygody; chronią sprawdzenia po stronie serwera.
7. Zapisuj wrażliwe działania w logu
Zapisuj, kto zmienił role, usunął dane lub wyeksportował rekordy, i kiedy. Dziennik audytu pomaga przy pytaniach od wsparcia i przy incydentach.
8. Testuj jak atakujący
Zaloguj się jako każda rola i spróbuj każdego działania z tabeli uprawnień. Potem spróbuj tego, co nie powinno działać: wywołaj trasę API dla administratora jako przeglądający, zmień ID w adresach URL i żądaniach, usuń siebie jako ostatniego właściciela. Testy automatyczne dla tabeli uprawnień warto napisać, gdy reguły się ustabilizują.
Prompty, które działają
Dodaj kontrolę dostępu opartą na rolach. Role w obrębie organizacji: owner, admin, member, viewer, przechowywane w tabeli memberships. Uprawnienia są w tej tabeli: [wklej swoją tabelę]. Utwórz jedną pomocniczą funkcję po stronie serwera can(user, action, resource), domyślnie odmawiającą, i użyj jej w każdej trasie API. Ograniczaj każde zapytanie przez organization_id. Ukrywaj w interfejsie działania niedostępne dla użytkownika, ale nigdy nie polegaj na tym pod kątem bezpieczeństwa.
Przejrzyj każdą trasę API i każdą funkcję serwerową w tej aplikacji. Dla każdej wypisz, jakie dane odczytuje lub zmienia, czy sprawdza, że użytkownik jest zalogowany, czy sprawdza jego rolę i czy ogranicza zapytanie do jego organizacji. Napraw brakujące sprawdzenia i pokaż mi listę.
Dodaj stronę /admin dostępną tylko dla właściciela, na której może on zmieniać role członków. Zablokuj usunięcie lub zdegradowanie ostatniego właściciela, zapisuj każdą zmianę roli wraz z tym, kto ją wykonał i kiedy, i upewnij się, że endpoint zmiany ról odrzuca każdego, kto nie jest właścicielem.
Częste błędy
- Sprawdzanie ról tylko w front endzie. API nadal jest otwarte dla każdego, kto je wywoła.
- Ufanie ID z klienta —
userIdlubrolew treści żądania zamiast z sesji. - Zapytania bez ograniczeń, które pobierają rekord wyłącznie po ID.
- Role sprawdzane na stronach, ale nie na trasach API, w eksportach, pobieraniu plików czy webhookach.
- Administrator po adresie e-mail wpisany na sztywno w kodzie (
if email === 'me@...'), łatwy do zapomnienia i trudny do zmiany. - Zbyt wiele ról zbyt wcześnie, których nikt nie wyjaśni pół roku później.
- Nieaktualne sesje: zdegradowany użytkownik zachowuje uprawnienia administratora, dopóki się nie wyloguje. Przy wrażliwych działaniach sprawdzaj role w bazie danych lub je odświeżaj.
Lista kontrolna RBAC
- Tabela uprawnień spisana prostym językiem, przypadki brzegowe rozstrzygnięte
- Serwer zna użytkownika z sesji, nigdy z danych żądania
- Role przechowywane w bazie danych; użytkownicy nie mogą zmieniać własnych
- Jedna centralna kontrola uprawnień, domyślnie odmawiająca, używana w każdej trasie
- Każde zapytanie ograniczone do organizacji lub własności użytkownika
- Row-level security tam, gdzie przeglądarka może sięgnąć do bazy
- Interfejs ukrywa to, czego użytkownicy nie mogą zrobić (tylko dla wygody)
- Wrażliwe działania zapisywane w logu
- Każda rola przetestowana, także przez bezpośrednie wywołania API i zmienione ID
Kontrola dostępu to jeden punkt z dłuższej listy; lista kontrolna bezpieczeństwa dla aplikacji zbudowanych z AI omawia resztę. Jeśli budujesz narzędzie dla własnego personelu, jak zbudować wewnętrzne narzędzie pokazuje, gdzie pasują role.
RBAC w Mythex
Mythex nie udostępnia wbudowanego systemu logowania ani ról dla użytkowników Twojej aplikacji. Wybierasz bibliotekę uwierzytelniania lub dostawcę i opisujesz role, a agent wpina je w Twój kod i w bazę Postgres projektu (dodawanie logowania do aplikacji). Role w przestrzeni roboczej Mythex, np. Właściciel i Członek, określają, kto może edytować Twoje projekty w Mythex, a nie kto może korzystać z opublikowanej aplikacji. Użyj trybu planowania, aby uzgodnić tabelę uprawnień przed budową, potem użyj powyższego promptu do przeglądu i przetestuj każdą rolę w podglądzie, zanim opublikujesz. Przydatnym kolejnym krokiem są prompty dotyczące bezpieczeństwa z dokumentacji.
Pytania
Czym jest kontrola dostępu oparta na rolach?
Kontrola dostępu oparta na rolach (RBAC) decyduje, co każdy użytkownik może robić, na podstawie posiadanych ról, np. administratora, edytora lub przeglądającego. Uprawnienia przypisuje się do ról, a nie do pojedynczych osób, więc zmiana tego, co ktoś może robić, sprowadza się do zmiany jego roli.
Jaka jest różnica między uwierzytelnianiem a autoryzacją?
Uwierzytelnianie sprawdza, kim ktoś jest, zwykle przez logowanie. Autoryzacja decyduje, co zalogowana osoba może zobaczyć i robić. RBAC to jeden ze sposobów realizacji autoryzacji.
Czy samo ukrycie przycisków w interfejsie wystarczy, aby ograniczyć dostęp?
Nie. Każdy może wywołać Twoje API bezpośrednio, więc ukrycie przycisku zmienia tylko to, co ludzie widzą. Każde żądanie odczytujące lub zmieniające dane trzeba sprawdzić na serwerze pod kątem roli użytkownika i tego, czy jest właścicielem rekordu.
Czy powinienem użyć row-level security w Postgresie?
Row-level security pozwala samej bazie danych wymuszać, które wiersze każdy użytkownik może odczytać lub zapisać. To mocna siatka bezpieczeństwa, zwłaszcza gdy front end rozmawia z bazą bezpośrednio. Dodaje jednak złożoności, dlatego wiele aplikacji egzekwuje uprawnienia w kodzie serwera, a row-level security stosuje jako dodatkową warstwę dla wrażliwych tabel.