Các tùy chọn bao gồm:
-
Khi bạn mở một kết nối,
CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user');
. Sau đó, trong trình kích hoạt của bạn,SELECT username FROM current_app_user
để lấy tên người dùng hiện tại, có thể là một truy vấn con. -
Trong
postgresql.conf
tạo một mục nhập cho một GUC tùy chỉnh nhưmy_app.username = 'unknown';
. Bất cứ khi nào bạn tạo kết nối, hãy chạySET my_app.username = 'the_user';
. Sau đó, trong trình kích hoạt, sử dụngcurrent_setting('my_app.username')
để lấy giá trị. Một cách hiệu quả, bạn đang lạm dụng máy móc GUC để cung cấp các biến phiên. Đọc tài liệu thích hợp với phiên bản máy chủ của bạn, vì GUC tùy chỉnh đã thay đổi trong 9.2 . -
Điều chỉnh ứng dụng của bạn để nó có các vai trò cơ sở dữ liệu cho mọi người dùng ứng dụng.
SET ROLE
cho người dùng đó trước khi thực hiện công việc. Điều này không chỉ cho phép bạn sử dụngcurrent_user
tích hợp sẵn hàm giống biến thànhSELECT current_user;
, nó cũng cho phép bạn thực thi bảo mật trong cơ sở dữ liệu . Xem câu hỏi này. Bạn có thể đăng nhập trực tiếp với tư cách người dùng thay vì sử dụngSET ROLE
, nhưng điều đó có xu hướng làm cho việc tổng hợp kết nối trở nên khó khăn.
Trong cả ba trường hợp bạn đang gộp kết nối, bạn phải cẩn thận DISCARD ALL;
khi bạn trả về một kết nối với pool. (Mặc dù nó không được ghi lại là làm như vậy, hãy DISCARD ALL
thực hiện RESET ROLE
).
Thiết lập chung cho các bản 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();
Sử dụng GUC:
- Trong
CUSTOMIZED OPTIONS
phần củapostgresql.conf
, thêm một dòng nhưmyapp.username = 'unknown_user'
. Trên các phiên bản PostgreSQL cũ hơn 9.2, bạn cũng phải đặtcustom_variable_classes = 'myapp'
. - Khởi động lại PostgreSQL. Bây giờ bạn sẽ có thể
SHOW myapp.username
và nhận giá trịunknown_user
.
Bây giờ bạn có thể sử dụng SET myapp.username = 'the_user';
khi bạn thiết lập kết nối, hoặc thay thế SET LOCAL myapp.username = 'the_user';
sau BEGIN
bắt đầu một giao dịch nếu bạn muốn nó là giao dịch cục bộ, điều này thuận tiện cho các kết nối tổng hợp.
get_app_user
định nghĩa hàm:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT current_setting('myapp.username');
$$ LANGUAGE sql;
Demo sử dụng SET LOCAL
cho tên người dùng hiện tại địa phương giao dịch:
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)
Nếu bạn sử dụng SET
thay vì SET LOCAL
cài đặt sẽ không được hoàn nguyên vào thời gian cam kết / khôi phục, vì vậy nó sẽ liên tục trong suốt phiên. Nó vẫn được đặt lại bằng 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)
Ngoài ra, lưu ý rằng bạn không thể sử dụng SET
hoặc SET LOCAL
với các tham số ràng buộc phía máy chủ. Nếu bạn muốn sử dụng các tham số ràng buộc ("câu lệnh chuẩn bị"), hãy xem xét sử dụng biểu mẫu hàm set_config(...)
. Xem các chức năng quản trị hệ thống
Sử dụng bảng tạm thời
Cách tiếp cận này yêu cầu sử dụng một trình kích hoạt (hoặc chức năng trợ giúp được gọi bởi trình kích hoạt, tốt hơn là) cố gắng đọc một giá trị từ một bảng tạm thời mà mọi phiên nên có. Nếu không tìm thấy bảng tạm thời, giá trị mặc định sẽ được cung cấp. Điều này có thể hơi chậm . Kiểm tra cẩn thận.
get_app_user()
định nghĩa:
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
Các biến phiên bảo mật
Ngoài ra còn có một đề xuất để thêm "các biến phiên bảo mật" vào PostgreSQL. Đây là một chút giống như các biến gói. Kể từ PostgreSQL 12, tính năng này vẫn chưa được bao gồm, nhưng hãy để ý và lên tiếng về danh sách tin tặc nếu đây là thứ bạn cần.
Nâng cao:tiện ích mở rộng của riêng bạn với vùng bộ nhớ dùng chung
Đối với các mục đích sử dụng nâng cao, bạn thậm chí có thể có phần mở rộng C của riêng mình đăng ký một vùng bộ nhớ được chia sẻ và giao tiếp giữa các phần phụ trợ bằng cách sử dụng các lệnh gọi hàm C đọc / ghi các giá trị trong một phân đoạn DSA. Xem các ví dụ lập trình PostgreSQL để biết chi tiết. Bạn sẽ cần kiến thức C, thời gian và sự kiên nhẫn.