Pilihannya meliputi:
-
Saat Anda membuka koneksi,
CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user');
. Kemudian di pemicu Anda,SELECT username FROM current_app_user
untuk mendapatkan nama pengguna saat ini, mungkin sebagai subkueri. -
Di
postgresql.conf
buat entri untuk GUC khusus sepertimy_app.username = 'unknown';
. Setiap kali Anda membuat koneksi, jalankanSET my_app.username = 'the_user';
. Kemudian di pemicu, gunakancurrent_setting('my_app.username')
berfungsi untuk mendapatkan nilai Secara efektif, Anda menyalahgunakan mesin GUC untuk menyediakan variabel sesi. Baca dokumentasi yang sesuai dengan versi server Anda, karena GUC khusus diubah di 9.2 . -
Sesuaikan aplikasi Anda sehingga memiliki peran database untuk setiap pengguna aplikasi.
SET ROLE
kepada pengguna tersebut sebelum melakukan pekerjaan. Ini tidak hanya memungkinkan Anda menggunakancurrent_user
bawaan fungsi seperti variabel untukSELECT current_user;
, ini juga memungkinkan Anda untuk menegakkan keamanan dalam database . Lihat pertanyaan ini. Anda dapat masuk langsung sebagai pengguna daripada menggunakanSET ROLE
, tapi itu cenderung membuat penyatuan koneksi menjadi sulit.
Dalam kedua ketiga kasus, Anda menggabungkan koneksi, Anda harus berhati-hati untuk DISCARD ALL;
ketika Anda mengembalikan koneksi ke kolam. (Meskipun tidak didokumentasikan melakukannya, DISCARD ALL
melakukan RESET ROLE
).
Pengaturan umum untuk demo:
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();
Menggunakan GUC:
- Dalam
CUSTOMIZED OPTIONS
bagian daripostgresql.conf
, tambahkan baris sepertimyapp.username = 'unknown_user'
. Pada versi PostgreSQL yang lebih lama dari 9.2 Anda juga harus menyetelcustom_variable_classes = 'myapp'
. - Mulai ulang PostgreSQL. Anda sekarang dapat
SHOW myapp.username
dan dapatkan nilaiunknown_user
.
Sekarang Anda dapat menggunakan SET myapp.username = 'the_user';
saat Anda membuat koneksi, atau secara bergantian SET LOCAL myapp.username = 'the_user';
setelah BEGIN
ning transaksi jika Anda ingin transaksi lokal, yang nyaman untuk koneksi gabungan.
get_app_user
definisi fungsi:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT current_setting('myapp.username');
$$ LANGUAGE sql;
Demo menggunakan SET LOCAL
untuk nama pengguna transaksi-lokal saat ini:
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)
Jika Anda menggunakan SET
alih-alih SET LOCAL
pengaturan tidak akan dikembalikan pada waktu komit/kembalikan, jadi itu tetap ada di seluruh sesi. Itu masih disetel ulang dengan 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)
Juga, perhatikan bahwa Anda tidak dapat menggunakan SET
atau SET LOCAL
dengan parameter pengikatan sisi server. Jika Anda ingin menggunakan parameter bind ("pernyataan yang disiapkan"), pertimbangkan untuk menggunakan bentuk fungsi set_config(...)
. Lihat fungsi administrasi sistem
Menggunakan tabel sementara
Pendekatan ini memerlukan penggunaan pemicu (atau fungsi pembantu yang dipanggil oleh pemicu, lebih disukai) yang mencoba membaca nilai dari tabel sementara yang harus dimiliki setiap sesi. Jika tabel sementara tidak dapat ditemukan, nilai default diberikan. Ini mungkin agak lambat . Uji dengan cermat.
get_app_user()
definisi:
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
Variabel sesi aman
Ada juga proposal untuk menambahkan "variabel sesi aman" ke PostgreSQL. Ini sedikit seperti variabel paket. Pada PostgreSQL 12 fitur tersebut belum disertakan, tetapi perhatikan dan sebutkan daftar peretas jika ini adalah sesuatu yang Anda butuhkan.
Lanjutan:ekstensi Anda sendiri dengan area memori bersama
Untuk penggunaan lanjutan, Anda bahkan dapat memiliki ekstensi C sendiri yang mendaftarkan area memori bersama dan berkomunikasi antar backend menggunakan panggilan fungsi C yang membaca/menulis nilai dalam segmen DSA. Lihat contoh pemrograman PostgreSQL untuk detailnya. Anda membutuhkan pengetahuan C, waktu, dan kesabaran.