PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Предаване на потребителски идентификатор към задействания на PostgreSQL

Опциите включват:

  • Когато отворите връзка, 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 създайте запис за персонализиран GUC като my_app.username = 'unknown'; . Всеки път, когато създавате връзка, стартирайте SET my_app.username = 'the_user'; . След това в тригери използвайте current_setting('my_app.username') функция за получаване на стойността. На практика злоупотребявате с GUC машината, за да предоставите променливи на сесията. Прочетете документацията, подходяща за версията на вашия сървър, тъй като персонализираните GUC са променени в 9.2 .

  • Настройте приложението си така, че да има роли на база данни за всеки потребител на приложението. SET ROLE на този потребител, преди да свършите работа. Това не само ви позволява да използвате вградения current_user подобна на променлива функция за SELECT current_user; , също така ви позволява да наложите сигурност в базата данни . Вижте този въпрос. Можете да влезете директно като потребител, вместо да използвате SET ROLE , но това затруднява обединяването на връзки.

И в двата случая, когато обединявате връзки, трябва да внимавате да 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' . На версии на PostgreSQL, по-стари от 9.2, също трябва да зададете 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 да регистрира споделена област на паметта и да комуникира между бекендове, използвайки извиквания на C функции, които четат/записват стойности в DSA сегмент. Вижте примерите за програмиране на PostgreSQL за подробности. Ще ви трябват знания, време и търпение по C.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да сравните производителността на PostgreSQL

  2. Създайте множество екземпляри на Postgres на една и съща машина

  3. Каква е разликата между pg_table_size, pg_relation_size и pg_total_relation_size? (PostgreSQL)

  4. Как да използвате Joda-Time с java.sql.Timestamp

  5. SQL функцията е много бавна в сравнение със заявка без обвивка на функция