PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Przekazywanie identyfikatora użytkownika do wyzwalaczy PostgreSQL

Opcje obejmują:

  • Po otwarciu połączenia CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user'); . Następnie w wyzwalaczu SELECT username FROM current_app_user aby uzyskać aktualną nazwę użytkownika, prawdopodobnie jako podzapytanie.

  • W postgresql.conf utwórz wpis dla niestandardowego GUC, takiego jak my_app.username = 'unknown'; . Za każdym razem, gdy tworzysz połączenie, uruchom SET my_app.username = 'the_user'; . Następnie w wyzwalaczach użyj current_setting('my_app.username') funkcja do uzyskania wartości. W rzeczywistości nadużywasz maszynerii GUC, aby zapewnić zmienne sesji. Przeczytaj dokumentację odpowiednią dla Twojej wersji serwera, ponieważ niestandardowe GUC zmieniły się w wersji 9.2 .

  • Dostosuj swoją aplikację tak, aby miała role bazy danych dla każdego użytkownika aplikacji. SET ROLE do tego użytkownika przed wykonaniem pracy. Pozwala to nie tylko na użycie wbudowanego current_user funkcja podobna do zmiennej do SELECT current_user; , umożliwia także wymuszanie bezpieczeństwa w bazie danych . Zobacz to pytanie. Możesz zalogować się bezpośrednio jako użytkownik zamiast używać SET ROLE , ale to zwykle utrudnia łączenie połączeń.

W obu trzech przypadkach puli połączeń musisz uważać, aby DISCARD ALL; po zwróceniu połączenia do puli. (Chociaż nie jest to udokumentowane, DISCARD ALL wykonuje RESET ROLE ).

Wspólna konfiguracja dla wersji demonstracyjnych:

CREATE TABLE tg_demo(blah text);
INSERT INTO tg_demo(blah) VALUES ('spam'),('eggs');

-- Placeholder; will be replaced by demo functions
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT 'unknown';
$$ LANGUAGE sql;

CREATE OR REPLACE FUNCTION tg_demo_trigger() RETURNS trigger AS $$
BEGIN
    RAISE NOTICE 'Current user is: %',get_app_user();
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER tg_demo_tg
AFTER INSERT OR UPDATE OR DELETE ON tg_demo 
FOR EACH ROW EXECUTE PROCEDURE tg_demo_trigger();

Korzystanie z GUC:

  • W CUSTOMIZED OPTIONS sekcja postgresql.conf , dodaj wiersz, taki jak myapp.username = 'unknown_user' . W wersjach PostgreSQL starszych niż 9.2 musisz również ustawić custom_variable_classes = 'myapp' .
  • Uruchom ponownie PostgreSQL. Teraz będziesz mógł SHOW myapp.username i uzyskaj wartość unknown_user .

Teraz możesz użyć SET myapp.username = 'the_user'; podczas nawiązywania połączenia lub alternatywnie SET LOCAL myapp.username = 'the_user'; po BEGIN transakcji, jeśli chcesz, aby była lokalna dla transakcji, co jest wygodne w przypadku połączeń w puli.

get_app_user definicja funkcji:

CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
    SELECT current_setting('myapp.username');
$$ LANGUAGE sql;

Demo za pomocą SET LOCAL dla bieżącej nazwy użytkownika dla transakcji:

regress=> BEGIN;
BEGIN
regress=> SET LOCAL myapp.username = 'test_user';
SET
regress=> INSERT INTO tg_demo(blah) VALUES ('42');
NOTICE:  Current user is: test_user
INSERT 0 1
regress=> COMMIT;
COMMIT
regress=> SHOW myapp.username;
 myapp.username 
----------------
 unknown_user
(1 row)

Jeśli używasz SET zamiast SET LOCAL ustawienie nie zostanie przywrócone w czasie zatwierdzenia/wycofania, więc jest trwałe w całej sesji. Nadal jest resetowany przez DISCARD ALL :

regress=> SET myapp.username = 'test';
SET
regress=> SHOW myapp.username;
 myapp.username 
----------------
 test
(1 row)

regress=> DISCARD ALL;
DISCARD ALL
regress=> SHOW myapp.username;
 myapp.username 
----------------
 unknown_user
(1 row)

Pamiętaj też, że nie możesz użyć SET lub SET LOCAL z parametrami wiązania po stronie serwera. Jeśli chcesz użyć parametrów wiązania ("przygotowanych instrukcji"), rozważ użycie formularza funkcji set_config(...) . Zobacz funkcje administracyjne systemu

Korzystanie z tabeli tymczasowej

To podejście wymaga użycia wyzwalacza (lub funkcji pomocniczej wywoływanej przez wyzwalacz), który próbuje odczytać wartość z tabeli tymczasowej, którą powinna mieć każda sesja. Jeśli nie można znaleźć tabeli tymczasowej, podawana jest wartość domyślna. To prawdopodobnie będzie trochę powolne . Przetestuj dokładnie.

get_app_user() definicja:

CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
DECLARE
    cur_user text;
BEGIN
    BEGIN
        cur_user := (SELECT username FROM current_app_user);
    EXCEPTION WHEN undefined_table THEN
        cur_user := 'unknown_user';
    END;
    RETURN cur_user;
END;
$$ LANGUAGE plpgsql VOLATILE;

Demo:

regress=> CREATE TEMPORARY TABLE current_app_user(username text);
CREATE TABLE
regress=> INSERT INTO current_app_user(username) VALUES ('testuser');
INSERT 0 1
regress=> INSERT INTO tg_demo(blah) VALUES ('42');
NOTICE:  Current user is: testuser
INSERT 0 1
regress=> DISCARD ALL;
DISCARD ALL
regress=> INSERT INTO tg_demo(blah) VALUES ('42');
NOTICE:  Current user is: unknown_user
INSERT 0 1

Bezpieczne zmienne sesji

Istnieje również propozycja dodania "bezpiecznych zmiennych sesji" do PostgreSQL. Przypominają trochę zmienne pakietu. Od PostgreSQL 12 ta funkcja nie została uwzględniona, ale miej oko na listę hakerów, jeśli jest to coś, czego potrzebujesz.

Zaawansowane:własne rozszerzenie ze współdzielonym obszarem pamięci

W przypadku zaawansowanych zastosowań możesz nawet mieć własne rozszerzenie C, które rejestruje obszar pamięci współdzielonej i komunikuje się między backendami za pomocą wywołań funkcji C, które odczytują/zapisują wartości w segmencie DSA. Zobacz przykłady programowania PostgreSQL, aby uzyskać szczegółowe informacje. Będziesz potrzebować wiedzy C, czasu i cierpliwości.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Entity Framework core — zawiera czy wielkość liter jest rozróżniana lub wielkość liter nie jest rozróżniana?

  2. Nie można po prostu użyć nazwy tabeli PostgreSQL (relacja nie istnieje)

  3. Jaki jest najbardziej elegancki sposób przechowywania znacznika czasu za pomocą nanosec w postgresql?

  4. Kontynuacja transakcji po błędzie naruszenia klucza podstawowego

  5. Instalacja PostgreSQL 9 w systemie Windows:Nie można pisać w ścieżce środowiska TEMP.