2013-11-21 3 views
1

Company_ID = 90에 속하는 JAdmin, PAdmin 및 Company_ID = 91에 속한 FAdmin, KAdmin과 같은 관리자 사용자가있을 경우 VPD를 작성했습니다. Employee에 다른 직원이 있습니다 두 회사에 속한 테이블. 거기에는 Timesheet, Payroll_Period 등과 같은 두 회사의 정보가있는 다른 테이블이 있습니다. Admin_ 및 Company_ID의 목록을 보유하는 Company_Administrators라는 테이블도 있습니다. 목표는 Set_Context를 사용하여 로그인 할 때 Admins의 company_ID를 가져 와서 회사의 정보 만 표시하는 것입니다. 코드 : 나는 관리자의로 로그인 선택 쿼리를 수행 할 때Oracle VPD 'Set_Context'가 작동하지 않습니다.

CREATE USER JAdmin IDENTIFIED BY JAdmin 
DEFAULT TABLESPACE IA643_TBS 
TEMPORARY TABLESPACE TEMP 
ACCOUNT UNLOCK; 

CREATE USER FAdmin IDENTIFIED BY FAdmin 
DEFAULT TABLESPACE IA643_TBS 
TEMPORARY TABLESPACE TEMP 
ACCOUNT UNLOCK; 

CREATE USER PAdmin IDENTIFIED BY PAdmin 
DEFAULT TABLESPACE IA643_TBS 
TEMPORARY TABLESPACE TEMP 
ACCOUNT UNLOCK; 

CREATE USER KAdmin IDENTIFIED BY KAdmin 
DEFAULT TABLESPACE IA643_TBS 
TEMPORARY TABLESPACE TEMP 
ACCOUNT UNLOCK; 

GRANT CONNECT, RESOURCE TO JAdmin; 
GRANT CONNECT, RESOURCE TO FAdmin; 
GRANT CONNECT, RESOURCE TO PAdmin; 
GRANT CONNECT, RESOURCE TO KAdmin; 

CREATE OR REPLACE PUBLIC SYNONYM COMPANY 
FOR DBA643.COMPANY; 
GRANT INSERT, SELECT, UPDATE, DELETE ON COMPANY 
TO FAdmin, JAdmin, PAdmin, KAdmin; 

CREATE OR REPLACE PUBLIC SYNONYM EMPLOYEE 
FOR DBA643.EMPLOYEE; 
GRANT INSERT, SELECT, UPDATE, DELETE ON EMPLOYEE 
TO FAdmin, JAdmin, PAdmin, KAdmin; 

CREATE OR REPLACE PUBLIC SYNONYM TIMESHEET 
FOR DBA643.TIMESHEET; 
GRANT INSERT, SELECT, UPDATE, DELETE ON TIMESHEET 
TO FAdmin, JAdmin, PAdmin, KAdmin; 

CREATE OR REPLACE PUBLIC SYNONYM PAYROLL_PERIOD 
FOR DBA643.PAYROLL_PERIOD; 
GRANT INSERT, SELECT, UPDATE, DELETE ON PAYROLL_PERIOD 
TO FAdmin, JAdmin, PAdmin, KAdmin; 

CREATE OR REPLACE PUBLIC SYNONYM DAILY_WORK_HOURS 
FOR DBA643.DAILY_WORK_HOURS; 
GRANT INSERT, SELECT, UPDATE, DELETE ON DAILY_WORK_HOURS 
TO FAdmin, JAdmin, PAdmin, KAdmin; 


Conn sys as sysdba 

CREATE USER sysadmin_ctx IDENTIFIED BY secAdmin; 
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER 
DATABASE TRIGGER TO sysadmin_ctx IDENTIFIED BY secAdmin; 
GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx; 
GRANT EXECUTE ON DBMS_RLS TO sysadmin_ctx; 
GRANT RESOURCE TO sysadmin_ctx; 

GRANT SELECT ON Company_Administrators TO sysadmin_ctx; 


CREATE OR REPLACE CONTEXT Company_Admin USING PKG_Comp_Admin; 
CREATE OR REPLACE PACKAGE PKG_Comp_Admin IS 
PROCEDURE Get_Company_ID; 
END; 
/
CREATE OR REPLACE PACKAGE BODY PKG_Comp_Admin IS 
PROCEDURE Get_Company_ID IS 
V_Company_ID NUMBER; 
BEGIN 
    SELECT Company_ID 
    INTO V_Company_ID 
    FROM DBA643.Company_Administrators 
    WHERE System_Username = SYS_CONTEXT('USERENV', 'SESSION_USER'); 
    DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', 'V_Company_ID'); 
    EXCEPTION 
    WHEN NO_DATA_FOUND THEN NULL; 
    END; 
END; 
/
SHOW ERROR; 



CREATE OR REPLACE FUNCTION Company_Admin_fun (P_schema_name IN varchar2, 
P_object_name IN varchar2) RETURN varchar2 IS 
V_where varchar2(300); 
BEGIN 
    IF User = 'DBA643' then 
    V_where := ''; 
ELSE 
    V_where := 'Company_ID = '||NVL(SYS_CONTEXT('Company_Admin', 'CompanyID'),0); 
    END IF; 
RETURN V_where; 
END; 
/


EXEC DBMS_RLS.DROP_Policy ('DBA643','COMPANY','COMPANY_POLICY'); 
EXEC DBMS_RLS.DROP_Policy ('DBA643','EMPLOYEE','EMPLOYEE_POLICY'); 
EXEC DBMS_RLS.DROP_Policy ('DBA643','TIMESHEET','TIMESHEET_POLICY'); 
EXEC DBMS_RLS.DROP_Policy ('DBA643','DAILY_WORK_HOURS','DAILY_WORK_HOURS_POLICY'); 


EXEC DBMS_RLS.ADD_Policy ('DBA643','COMPANY','COMPANY_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE); 
EXEC DBMS_RLS.ADD_Policy ('DBA643','EMPLOYEE','EMPLOYEE_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE); 
EXEC DBMS_RLS.ADD_Policy ('DBA643','TIMESHEET','TIMESHEET_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE); 
EXEC DBMS_RLS.ADD_Policy ('DBA643','DAILY_WORK_HOURS','DAILY_WORK_HOURS_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE); 


CREATE OR REPLACE TRIGGER After_Logon_Trigger 
AFTER LOGON 
ON DATABASE 
BEGIN 
    sysadmin_ctx.PKG_Comp_Admin.Get_Company_ID; 
END; 
/

, 내가 '선택 행이'수 없습니다. 관리자 중 하나로 로그인 한 후 다음 명령을 사용하면 관리자의 회사 ID가되어야하는 Company_Admin 컨텍스트의 업데이트 된 값이 표시되지 않기 때문에 Set_context 부분에 대한 문제를 줄였습니다.

select SYS_CONTEXT('Company_Admin', 'CompanyID') from dual 

어떤 도움을 주시면 감사하겠습니다. 고맙습니다.

+0

Pls가 태그로 VPD를 추가합니다. Oracle VPD는 Oracle의 Virtual Private Database를 참조합니다. – pahariayogi

답변

1

당신은 (리터럴 문자열 대신 변수 값의 V_Company_ID) 잘못된 값으로 컨텍스트를 설정하는 - 대신

DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', 'V_Company_ID'); 

의가 디버깅을위한

DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', V_Company_ID); 

몇 가지 더 제안해야한다 :

  • 사용자를 기록하는 sysadmin_ctx.PKG_Comp_Admin.Get_Company_ID 절차에 로그 항목을 작성하십시오.
  • 당신은 오라클 12C를 사용하는 경우 다음 VPD는 원래 SQL 문에 추가 것을 볼 수 dbms_utility.expand_sql_text를 사용
+0

감사합니다 Frank, 나는 그것을 시도했고 V_Company_ID 대신 정적 값을 사용하여 시도했지만 여전히 동일한 문제가 있습니다. 또한 Admin 사용자가 sysadmin_ctx 사용자로 작성한 컨텍스트 중 하나와 연관되어 있지 않음을 알았습니다. 따라서 set_context는 작동하지만 Admin 사용자는 연결하지 않습니다. –

0

는 전 세계적으로 절 액세스 할 수있는 와 컨텍스트를 만드는 시도?

set_context 작업이 컨텍스트 네임 스페이스를 쿼리하는 세션과 다른 세션에서 실행되는 경우 아무 데이터도 얻을 수 없습니다. ACCESSED GLOBALLY 절없이 작성된 컨텍스트는 세션 레벨의 데이터 만 보유합니다. ACCESSED GLOBALLY 절을 사용하여 데이터를 만들 때 데이터는 인스턴스 수준에서 액세스 할 수 있습니다.

PS I 컨텍스트는 (적어도 11gR2)에 알려진 옵션을 사용하지 않고, 서버의 RAM에 데이터를 보유하고 있다는 사실로 인해 RAC 레벨의 컨텍스트를 만드는 방법이 있다고 생각하지 않습니다

각 RAC 노드에 컨텍스트의 데이터를 복제하십시오. 또한 인스턴스 종료의 경우 데이터를 저장할 방법이 없다는 이유로 컨텍스트에 의존하는 것이 문제가됩니다 (기존 전역 변수 또는 전역 카운터로 사용하려는 경우 - 인스턴스 시작시 네임 스페이스의 데이터를 설정해야 함) 매번).

관련 문제