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_user
získat aktuální uživatelské jméno, případně jako dílčí dotaz. -
V
postgresql.conf
vytvoř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 ROLE
tomuto uživateli před provedením práce. To vám nejen umožňuje používat vestavěnýcurrent_user
funkce 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.username
a 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.