PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Meneruskan id pengguna ke pemicu PostgreSQL

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 seperti my_app.username = 'unknown'; . Setiap kali Anda membuat koneksi, jalankan SET my_app.username = 'the_user'; . Kemudian di pemicu, gunakan current_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 menggunakan current_user bawaan fungsi seperti variabel untuk SELECT current_user; , ini juga memungkinkan Anda untuk menegakkan keamanan dalam database . Lihat pertanyaan ini. Anda dapat masuk langsung sebagai pengguna daripada menggunakan SET 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 dari postgresql.conf , tambahkan baris seperti myapp.username = 'unknown_user' . Pada versi PostgreSQL yang lebih lama dari 9.2 Anda juga harus menyetel custom_variable_classes = 'myapp' .
  • Mulai ulang PostgreSQL. Anda sekarang dapat SHOW myapp.username dan dapatkan nilai unknown_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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails:Tidak ada kumpulan koneksi untuk ActiveRecord::Base

  2. Tidak dapat menemukan pustaka klien PostgreSQL (libpq)

  3. Bagaimana cara mengubah skema beberapa tabel PostgreSQL dalam satu operasi?

  4. Mengapa pg_restore berhasil kembali tetapi tidak benar-benar memulihkan database saya?

  5. Mentranspos hasil sql sehingga satu kolom masuk ke beberapa kolom