Možnosti zahrnují:
-
Když otevřete připojení,
CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user');. Poté ve spouštěčiSELECT username FROM current_app_userzískat aktuální uživatelské jméno, případně jako dílčí dotaz. -
V
postgresql.confvytvořte záznam pro vlastní GUC, jako jemy_app.username = 'unknown';. Kdykoli vytvoříte připojení, spusťteSET my_app.username = 'the_user';. Poté ve spouštěčích použijtecurrent_setting('my_app.username')funkce k získání hodnoty. Ve skutečnosti zneužíváte stroje GUC k poskytování proměnných relace. Přečtěte si dokumentaci odpovídající verzi vašeho serveru, protože vlastní GUC se ve verzi 9.2 změnily . -
Upravte svou aplikaci tak, aby měla databázové role pro každého uživatele aplikace.
SET ROLEtomuto uživateli před provedením práce. To vám nejen umožňuje používat vestavěnýcurrent_userfunkce podobná proměnné naSELECT current_user;, také vám umožňuje vynutit zabezpečení databáze . Viz tato otázka. Můžete se přihlásit přímo jako uživatel namísto použitíSET ROLE, ale to má tendenci ztěžovat sdružování připojení.
V obou všech třech případech, kdy sdružujete připojení, musíte být opatrní, abyste DISCARD ALL; když obnovíte připojení k bazénu. (Ačkoli to není zdokumentováno, DISCARD ALL provede RESET ROLE ).
Běžné nastavení pro ukázky:
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();
Použití GUC:
- V
CUSTOMIZED OPTIONSčástipostgresql.conf, přidejte řádek jakomyapp.username = 'unknown_user'. Na verzích PostgreSQL starších než 9.2 musíte také nastavitcustom_variable_classes = 'myapp'. - Restartujte PostgreSQL. Nyní budete moci
SHOW myapp.usernamea získejte hodnotuunknown_user.
Nyní můžete použít SET myapp.username = 'the_user'; když navážete připojení, nebo alternativně SET LOCAL myapp.username = 'the_user'; po BEGIN Pokud chcete, aby byla transakce lokální, což je výhodné pro sdružená připojení.
get_app_user definice funkce:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT current_setting('myapp.username');
$$ LANGUAGE sql;
Ukázka pomocí SET LOCAL pro aktuální uživatelské jméno transakce:
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)
Pokud použijete SET místo SET LOCAL nastavení se při odevzdání/rollbacku nevrátí, takže je trvalé po celou dobu relace. Stále se resetuje pomocí 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)
Pamatujte také, že nemůžete použít SET nebo SET LOCAL s parametry vazby na straně serveru. Pokud chcete použít parametry vazby ("připravené příkazy"), zvažte použití formuláře funkce set_config(...) . Viz funkce správy systému
Použití dočasné tabulky
Tento přístup vyžaduje použití spouštěče (nebo raději pomocné funkce volané spouštěčem), který se pokouší načíst hodnotu z dočasné tabulky, kterou by měla mít každá relace. Pokud dočasnou tabulku nelze najít, je poskytnuta výchozí hodnota. To bude pravděpodobně poněkud pomalé . Pečlivě testujte.
get_app_user() definice:
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
Zabezpečené proměnné relace
Existuje také návrh přidat do PostgreSQL „proměnné zabezpečené relace“. Jsou to trochu jako proměnné balíčku. Od PostgreSQL 12 tato funkce nebyla zahrnuta, ale dávejte pozor a ozvěte se na seznamu hackerů, pokud to potřebujete.
Pokročilé:vaše vlastní rozšíření s oblastí sdílené paměti
Pro pokročilé použití můžete dokonce nechat své vlastní rozšíření C zaregistrovat oblast sdílené paměti a komunikovat mezi backendy pomocí volání funkcí C, které čtou/zapisují hodnoty v segmentu DSA. Podrobnosti najdete v příkladech programování PostgreSQL. Budete potřebovat znalosti jazyka C, čas a trpělivost.