Indstillinger omfatter:
-
Når du åbner en forbindelse,
CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user');
. I din trigger,SELECT username FROM current_app_user
for at få det aktuelle brugernavn, eventuelt som en underforespørgsel. -
I
postgresql.conf
opret en post for en tilpasset GUC sommy_app.username = 'unknown';
. Hver gang du opretter en forbindelse, kørSET my_app.username = 'the_user';
. I triggere skal du derefter brugecurrent_setting('my_app.username')
funktion for at opnå værdien. Faktisk misbruger du GUC-maskineriet til at levere sessionsvariabler. Læs dokumentationen, der passer til din serverversion, da tilpassede GUC'er blev ændret i 9.2 . -
Juster din applikation, så den har databaseroller for hver applikationsbruger.
SET ROLE
til den pågældende bruger, før arbejdet udføres. Dette lader dig ikke kun bruge den indbyggedecurrent_user
variabel-lignende funktion tilSELECT current_user;
, det giver dig også mulighed for at håndhæve sikkerheden i databasen . Se dette spørgsmål. Du kan logge ind direkte som bruger i stedet for at brugeSET ROLE
, men det har en tendens til at gøre forbindelsespooling svær.
I begge alle tre tilfælde, hvor du samler forbindelse, skal du være omhyggelig med at DISCARD ALL;
når du returnerer en forbindelse til poolen. (Selvom det ikke er dokumenteret at gøre det, DISCARD ALL
udfører en RESET ROLE
).
Fælles opsætning for demoer:
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();
Brug af en GUC:
- I
CUSTOMIZED OPTIONS
sektion afpostgresql.conf
, tilføj en linje sommyapp.username = 'unknown_user'
. På PostgreSQL-versioner ældre end 9.2 skal du også indstillecustom_variable_classes = 'myapp'
. - Genstart PostgreSQL. Du vil nu være i stand til at
SHOW myapp.username
og få værdienunknown_user
.
Nu kan du bruge SET myapp.username = 'the_user';
når du etablerer en forbindelse, eller alternativt SET LOCAL myapp.username = 'the_user';
efter BEGIN
ning af en transaktion, hvis du ønsker, at den skal være transaktionslokal, hvilket er praktisk for poolede forbindelser.
get_app_user
funktionsdefinition:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT current_setting('myapp.username');
$$ LANGUAGE sql;
Demo ved hjælp af SET LOCAL
for transaktionslokalt nuværende brugernavn:
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)
Hvis du bruger SET
i stedet for SET LOCAL
indstillingen bliver ikke vendt tilbage ved commit/rollback-tidspunkt, så den er vedvarende i hele sessionen. Det er stadig nulstillet af 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)
Bemærk også, at du ikke kan bruge SET
eller SET LOCAL
med bindingsparametre på serversiden. Hvis du vil bruge bindeparametre ("forberedte sætninger"), kan du overveje at bruge funktionsformen set_config(...)
. Se systemadministrationsfunktioner
Brug af en midlertidig tabel
Denne tilgang kræver brug af en trigger (eller hjælperfunktion kaldet af en trigger, helst), der forsøger at læse en værdi fra en midlertidig tabel, hver session skal have. Hvis den midlertidige tabel ikke kan findes, leveres en standardværdi. Dette vil sandsynligvis være lidt langsomt . Test omhyggeligt.
get_app_user()
definition:
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
Sikrede sessionsvariabler
Der er også et forslag om at tilføje "sikre sessionsvariabler" til PostgreSQL. Disse er lidt ligesom pakkevariabler. Fra og med PostgreSQL 12 er funktionen ikke inkluderet, men hold øje og fortæl hackerlisten, hvis det er noget du har brug for.
Avanceret:din egen udvidelse med delt hukommelsesområde
Til avanceret brug kan du endda få din egen C-udvidelse til at registrere et delt hukommelsesområde og kommunikere mellem backends ved hjælp af C-funktionskald, der læser/skriver værdier i et DSA-segment. Se PostgreSQL-programmeringseksemplerne for detaljer. Du skal bruge C viden, tid og tålmodighed.