[Oracle ADF] Row Level Security using VPD and ADF - Шаг 1 - Настраиваем контексты, процедуры, подготавливаем appmodule


По материалам: Row level Security using ADF and Sys_context package

http://dba-adf.blogspot.ru/2012/07/row-level-security-using-adf-and.html


ШАГ 1:

Выполняется под учеткой пользователя в базе данных! В моем случае в SQL Developer.


Создаю контекстную переменную в базе, которая будет хранить залогиненого пользователя и обновляться при логине:


CREATE OR REPLACE CONTEXT SEC_CTX
 USING SEC_CTX_PKG
 ACCESSED GLOBALLY;



Далее базе создаю пакет:


create or replace PACKAGE SEC_CTX_PKG IS  
   PROCEDURE SET_SESSION_ID (IN_SESSION_ID VARCHAR2);  
   PROCEDURE SET_CONTEXT (IN_NAME VARCHAR2, IN_VALUE VARCHAR2);  
   FUNCTION RETURN_CONTEXT RETURN VARCHAR2;
 END SEC_CTX_PKG;


 create or replace PACKAGE BODY SEC_CTX_PKG  
  IS

    GC$SESSION_ID  VARCHAR2 (100);

    PROCEDURE SET_SESSION_ID (IN_SESSION_ID VARCHAR2)  
    IS  
    BEGIN  
     GC$SESSION_ID := IN_SESSION_ID;
     DBMS_SESSION.SET_IDENTIFIER (IN_SESSION_ID);
   END;  
 -------------------------------------------------------------------------------------------------
    PROCEDURE SET_CONTEXT (IN_NAME VARCHAR2, IN_VALUE VARCHAR2)  
    IS  
    BEGIN  
    DBMS_SESSION.SET_CONTEXT ('SEC_CTX', IN_NAME, IN_VALUE, USER, GC$SESSION_ID);  

    END;

 -------------------------------------------------------------------------------------------------

 FUNCTION RETURN_CONTEXT

     RETURN VARCHAR2 AS

      RES1 varchar2(80);

         BEGIN
            SELECT SYS_CONTEXT ('SEC_CTX', 'user_id') INTO RES1 FROM DUAL;
         RETURN RES1;

 END RETURN_CONTEXT;

 ------------------------------------------------------------------------------------------------

  END SEC_CTX_PKG;



В AppModuleImpl добавляю следующий код:
Код написан для тестирования! А не для того, чтобы поразить всех красотой и изяществом! И да, у меня он всегда такой получается!


@Override
protected void prepareSession(Session session) {
    super.prepareSession(session);
    setVPDcontext();
    checkContextFromDB();
}


private void setVPDcontext() {

    SessionImpl sessionImpl = (SessionImpl)getDBTransaction().getSession();
    String loggedInUser = sessionImpl.getUserPrincipalName();

    CallableStatement stmt = null;

           try {           
               String sql = "BEGIN  SEC_CTX_PKG.SET_SESSION_ID ('" + loggedInUser + "'); SEC_CTX_PKG.SET_CONTEXT ('user_id', '" + loggedInUser + "'); END; ";
               stmt = this.getDBTransaction().createCallableStatement(sql, 0);
               stmt.execute();
           } catch (Exception ex) {
               LOGGER.severe("EXCEPTION " + ex.toString());
               ex.printStackTrace();
           } finally {
               if (stmt != null) {
                   try {
                       stmt.close();
                   } catch (Exception ex) {
                       LOGGER.severe("EXCEPTION " + ex.toString());
                       ex.printStackTrace();
                   }
               }
           }
}



public void checkContextFromDB(){

    System.out.println("");
    System.out.println("");
    System.out.println("out " + getContextFromDB());
    System.out.println("");
    System.out.println("");

}



private String getContextFromDB(){
    CallableStatement stmt = null;
    String function_execute = "begin ?:= SEC_CTX_PKG.RETURN_CONTEXT; end;";

        try {
        stmt = this.getDBTransaction().createCallableStatement(function_execute, 1);

       stmt.registerOutParameter(1, Types.VARCHAR);

        stmt.execute();

         String out = stmt.getString(1);

        return out;

    } catch (Exception exp) {

            System.out.println("EXCEPTION EX " + exp.toString());

               // exp.printStackTrace();
           } finally {
               if (stmt != null) {
                   try {
                       stmt.close();
                   } catch (Exception exp) {
                       exp.printStackTrace();
                   }
               }
           }

   return "";
}


this.getDBTransaction() следует заменить DBUtils.getDBTransaction(), если делать вызов в каком-нибудь бине. Но когда я делал в бине, контекст время от времени терялся. Поэтому оставил в AppModule.


Теперь при логине получаю в консоли логин зарегистрированного пользователя.
И вывожу тоже самое из SEC_CTX.


Далее создаю ViewObject, что-то вроде:

SELECT *
     FROM user_info
    WHERE user_id = SYS_CONTEXT ('SEC_CTX', 'user_id');

И бросаю его на форму, конкретно в моем случае, это таблица.



Offtopic. Вроде можно и так сделать, а не как у автора статьи. Впрочем мне сейчас не до проверяния всего этого.

Работает, не трогай. Похвалить не похвалят, а сломаешь накажут.

PROCEDURE SET_SESSION_ID (IN_SESSION_ID VARCHAR2)  
IS  
BEGIN  
 DBMS_SESSION.SET_IDENTIFIER (IN_SESSION_ID);
END;  
-------------------------------------------------------------------------------------------------
PROCEDURE SET_CONTEXT (IN_NAME VARCHAR2, IN_VALUE VARCHAR2)  
IS  
BEGIN  

 DBMS_SESSION.SET_CONTEXT ('SEC_CTX', IN_NAME, IN_VALUE, USER);

END;