オプションは次のとおりです。
-
接続を開くと、
CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user');
。次に、トリガーで、SELECT username FROM current_app_user
おそらくサブクエリとして、現在のユーザー名を取得します。 -
postgresql.conf
内my_app.username = 'unknown';
のようなカスタムGUCのエントリを作成します 。接続を作成するときはいつでも、SET my_app.username = 'the_user';
を実行します。 。次に、トリガーで、current_setting('my_app.username')
を使用します 値を取得する関数。事実上、セッション変数を提供するためにGUC機構を悪用しています。 カスタムGUCは9.2で変更されたため、サーバーのバージョンに適したドキュメントをお読みください 。 -
すべてのアプリケーションユーザーのデータベースロールを持つようにアプリケーションを調整します。
SET ROLE
仕事をする前にそのユーザーに。これにより、組み込みのcurrent_user
を使用できるだけでなくSELECT current_user;
への変数のような関数 、データベースのセキュリティを強化することもできます。 。この質問を参照してください。SET ROLE
を使用する代わりに、ユーザーとして直接ログインできます。 、しかしそれは接続プールを難しくする傾向があります。
接続プールを使用している3つのケースすべてで、DISCARD ALL;
に注意する必要があります。 プールへの接続を返すとき。 (そのように文書化されていませんが、DISCARD ALL
RESET ROLE
を実行します 。
デモの一般的な設定:
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();
GUCの使用:
CUSTOMIZED OPTIONS
postgresql.conf
のセクション 、myapp.username = 'unknown_user'
のような行を追加します 。 9.2より古いバージョンのPostgreSQLでは、custom_variable_classes = 'myapp'
も設定する必要があります。 。- PostgreSQLを再起動します。これで、
SHOW myapp.username
ができるようになります 値unknown_user
を取得します 。
これで、SET myapp.username = 'the_user';
を使用できます。 接続を確立するとき、または代わりにSET LOCAL myapp.username = 'the_user';
BEGIN
の後 トランザクションをローカルにしたい場合は、トランザクションを作成します。これは、プールされた接続に便利です。
get_app_user
関数の定義:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT current_setting('myapp.username');
$$ LANGUAGE sql;
SET LOCAL
を使用したデモ トランザクションの場合-ローカルの現在のユーザー名:
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)
SET
を使用する場合 SET LOCAL
の代わりに 設定はコミット/ロールバック時に元に戻されないため、セッション全体で保持されます。それでも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)
また、SET
は使用できないことに注意してください またはSET LOCAL
サーバー側のバインドパラメータを使用します。バインドパラメータ(「プリペアドステートメント」)を使用する場合は、関数形式set_config(...)
の使用を検討してください。 。システム管理機能を参照してください
一時テーブルの使用
このアプローチでは、すべてのセッションで必要な一時テーブルから値を読み取ろうとするトリガー(またはトリガーによって呼び出されるヘルパー関数が望ましい)を使用する必要があります。一時テーブルが見つからない場合は、デフォルト値が提供されます。これはやや遅い可能性があります 。注意深くテストしてください。
get_app_user()
定義:
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;
デモ:
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
安全なセッション変数
PostgreSQLに「セキュアセッション変数」を追加する提案もあります。これらはパッケージ変数に少し似ています。 PostgreSQL 12の時点では、この機能は含まれていませんが、これが必要な場合は、ハッカーリストに注意して発言してください。
詳細:共有メモリ領域を備えた独自の拡張機能
高度な使用法では、独自のC拡張機能に共有メモリ領域を登録させ、DSAセグメントの値を読み取り/書き込みするC関数呼び出しを使用してバックエンド間で通信することもできます。詳細については、PostgreSQLのプログラミング例を参照してください。 Cの知識、時間、そして忍耐力が必要です。