Здравствуйте, я задал этот вопрос вчера, но благодаря вашей помощи я сделал много модификаций, так что теперь я помещаю новую версию своего кода, потому что она улучшается, но все еще не работает.
Предположим, у меня есть следующая таблица, которая называется payroll
, созданная пользователем с именем PCM
EMP_ID DEPT TOTAL TAXES
-------------------- -------------------- ---------- ----------
E1 accounting 2400 100
E2 sales 2500 75
E3 research 3000 110
E4 operations 4200 120
E5 sales 4800 130
E6 sales 2500 75
E7 accounting 5200 140
E8 accounting 2700 105
Теперь я хочу добиться следующего: Любой, у кого есть dept = accounting"
может выбрать все остальные строки с помощью dept != accounting
, но любой пользователь с dept != accounting
может только просматривать свою запись.
Теперь я подключен как другой пользователь, не являющийся владельцем таблицы заработной платы, поэтому яподключен как пользователь с именем ANNE
:
CREATE OR REPLACE CONTEXT payroll_ctx USING payroll_ctx_pkg;
CREATE OR REPLACE PACKAGE payroll_ctx_pkg IS
PROCEDURE set_dept;
END;
/
CREATE OR REPLACE PACKAGE BODY payroll_ctx_pkg IS
PROCEDURE set_dept
AS
v_dept varchar2(400);
BEGIN
SELECT dept INTO v_dept FROM PCM.PAYROLL
WHERE EMP_ID = SYS_CONTEXT('USERENV', 'SESSION_USER');
DBMS_SESSION.SET_CONTEXT('payroll_ctx', 'dept', v_dept);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_SESSION.SET_CONTEXT('payroll_ctx', 'dept', 'NO');
END set_dept;
END;
/
Учитывая, что пользователи, которые будут пытаться получить доступ к таблице, имеют имена столбца emp_id, теперь:
CREATE TRIGGER set_dept_trig AFTER LOGON ON DATABASE
BEGIN
ANNE.payroll_ctx_pkg.set_dept;
END;
/
Теперьпроблема (я знаю, что это неправильно), но пока не могу найти решение:
CREATE OR REPLACE PACKAGE security_package AS
FUNCTION sec_fun (D1 VARCHAR2, D2 VARCHAR2)
RETURN VARCHAR2;
END;
/
CREATE OR REPLACE PACKAGE BODY security_package AS
FUNCTION sec_fun (D1 VARCHAR2, D2 VARCHAR2)
RETURN VARCHAR2
IS
vv_dept varchar2(400);
V_ID varchar2(400);
begin
V_ID := SYS_CONTEXT('USERENV', 'SESSION_USER');
vv_dept := 'SYS_CONTEXT(''payroll_ctx'', ''dept'')';
if (vv_dept != 'accounting') then
RETURN 'EMP_ID = ' || CHR(39)||V_ID||CHR(39);
ELSE
RETURN 'DEPT != ' || CHR(39)||vv_dept||CHR(39);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN '1 = 0';
end sec_fun;
end security_package;
/
И наконец:
BEGIN
DBMS_RLS.ADD_POLICY (
object_schema => 'PCM',
object_name => 'PAYROLL',
policy_name => 'payroll_policy',
function_schema => 'ANNE',
policy_function => 'security_package.sec_fun',
statement_types => 'select');
END;
/
Теперь, когда пользователь E1
пытается выбрать из платежной ведомостивывод:
EMP_ID DEPT TOTAL TAXES
-------------------- -------------------- ---------- ----------
E1 accounting 2400 100
что я делаю не так ??Он должен вернуть все строки, где dept != accounting