Oracle Application Context详解(原创)

前端之家收集整理的这篇文章主要介绍了Oracle Application Context详解(原创)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

Application Context是内存中的一组name-value对,application context从属于某个命名空间(namespace)。
用 户只能通过一个自定义procedure调用dbms_session.set_context来设置application context的值。用户使用sys_context(<namespace>,<name>)来获取某个 application context的值。
Application context分为三种

  • dabase session-based application context,又称为local application context。Local application context存储在UGA中,dedicated server mode,UGA在PGA中,shared server mode,UGA在SGA中。local application context是会话/server process级别的。只有本会话能够访问。当会话/server process终止时,local application context的生命周期也结束了。另一篇博客Oracle VPD http://blog.csdn.net/chncaesar/article/details/18550029 给出了一个local application context的例子。
    • global application context,Global application context存储在SGA中,只要SGA不消亡,global application context就一直存在。global application context常常用于跨会话,与会话无关的场景。dbms_session.set_context有两个默认值为NULL的参数:
      username
      client_id
      username = null,client_id=null。所有用户都能访问。
      username = null,client_id=<client_id>。 只要session 的client_id =<client_id>,而不管username,都能访问。
      username = <database username>,client_id=null。只要session使用指定的oracle schema登陆,不管client_id,都能访问。
      username = <database username>,client_id=<client_id>. 常用于statless web session ,如http。
      username = <non-database username>,client_id=<client_id> . 该username将用于数据库连接池的owner。
  • client session-based application context。通常被OCI使用,存储在客户端内存,而不是Oracle服务器端,也由OCI程序管理。

实例

例子1: 所有用户都能访问的application context

CREATE OR REPLACE CONTEXT global_hr_ctx USING hr_ctx_pkg ACCESSED GLOBALLY;
CREATE OR REPLACE PACKAGE hr_ctx_pkg
AS
PROCEDURE set_hr_ctx(sec_level IN VARCHAR2);
PROCEDUREclear_hr_ctx;
END;
/
create or replace package body hr_ctx_pkg
as
procedure set_hr_ctx(sec_level in VARCHAR2)
BEGIN
DBMS_SESSION.SET_CONTEXT(
NAMESPACE => 'global_hr_ctx',
attribute => 'job_role',0)"> value => sec_level);
end set_hr_ctx;
procedure clear_hr_ctx
as
begin
dbms_session.clear_context('global_hr_ctx','job_role');
end clear_hr_ctx;
end;
/

sql> BEGIN
2 hr_ctx_pkg.set_hr_ctx('clerk');
3 END;
4 /

PL/sql procedure successfully completed.


sql> SELECT SYS_CONTEXT('global_hr_ctx','job_role') job_role FROM DUAL;
JOB_ROLE
------------------------------------
clerk

例子2: 跨session/application,但是使用同一个数据库schema的application context。

Setting a Global Context for Database Users Who Move Between Applications
CREATE OR REPLACE PACKAGE hr_ctx1_pkg
AS
PROCEDURE set_hr_ctx(sec_level IN VARCHAR2,user_name IN VARCHAR2);
PROCEDURE clear_hr_context;
END;
/
CREATE OR REPLACE PACKAGE BODY hr_ctx1_pkg
AS
PROCEDURE set_hr_ctx(sec_level IN VARCHAR2,user_name IN VARCHAR2)
AS
BEGIN
DBMS_SESSION.SET_CONTEXT(
namespace => 'global_hr_ctx',
attribute => 'job',
value => sec_level,
username => user_name); --- 这里的user_name表示用户数据库用户
END set_hr_ctx;
PROCEDURE clear_hr_context
AS
BEGIN
DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx');
END clear_hr_context;
END hr_ctx1_pkg;
/
例3 Tutorial: Creating a Global Application Context That Uses a Client Session ID

Step 1: Create User Accounts

You must create two users for this example: a security administrator who will manage the application context and its package,and a user account that owns the connection pool.

In this tutorial:

  1. Log on to sql*Plus asSYSand connect using@H_404_173@AS SYSDBA.

    sqlplus sys as sysdba
    Enter password: password
    
  2. Create the@H_404_173@sysadmin_ctxaccount,who will administer the global application context.

    GRANT CREATE SESSION,CREATE ANY CONTEXT,CREATE PROCEDURE TO sysadmin_ctx IDENTIFIED BY password;
    
    GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
    

    Replace@H_404_173@passwordwith a password that is secure. See"Minimum Requirements for Passwords"for more information.

  3. Create the database account@H_404_173@apps_user,who will own the connection pool.

    GRANT CREATE SESSION TO apps_user IDENTIFIED BY password;
    

    Replace"Minimum Requirements for Passwords"for more information.

Step 2: Create the Global Application Context

  1. Log on as the security administrator@H_404_173@sysadmin_ctx.

    CONNECT sysadmin_ctx
    Enter password: password
    
  2. Create the@H_404_173@cust_ctxglobal application context.

    CREATE CONTEXT global_cust_ctx USING cust_ctx_pkg ACCESSED GLOBALLY;
    

    The@H_404_173@cust_ctxcontext is created and associated with the schema of the security administrator@H_404_173@sysadmin_ctx. However,the@H_404_173@SYSschema owns the application context.

Step 3: Create a Package for the Global Application Context

  1. Assysadmin_ctx,create the following PL/SQL package:

    CREATE OR REPLACE PACKAGE cust_ctx_pkg
      AS
       PROCEDURE set_session_id(session_id_p IN NUMBER); 
       PROCEDURE set_cust_ctx(sec_level_attr IN VARCHAR2,sec_level_val IN VARCHAR2);
       PROCEDURE clear_hr_session(session_id_p IN NUMBER);
       PROCEDURE clear_hr_context;
      END;
     /
    CREATE OR REPLACE PACKAGE BODY cust_ctx_pkg
      AS
      session_id_global NUMBER;
     
     PROCEDURE set_session_id(session_id_p IN NUMBER) 
      AS
      BEGIN
       session_id_global := session_id_p;
       DBMS_SESSION.SET_IDENTIFIER(session_id_p);
     END set_session_id;
     
     PROCEDURE set_cust_ctx(sec_level_attr IN VARCHAR2,sec_level_val IN VARCHAR2)
      AS
      BEGIN
       DBMS_SESSION.SET_CONTEXT(
        namespace  => 'global_cust_ctx',attribute  => sec_level_attr,value      => sec_level_val,username   => USER,-- Retrieves the session user,in this case,apps_user
        client_id  => session_id_global);
      END set_cust_ctx;
     
      PROCEDURE clear_hr_session(session_id_p IN NUMBER)
       AS
       BEGIN
         DBMS_SESSION.SET_IDENTIFIER(session_id_p);
         DBMS_SESSION.CLEAR_IDENTIFIER;
       END clear_hr_session;
    
     PROCEDURE clear_hr_context
      AS
      BEGIN
       DBMS_SESSION.CLEAR_CONTEXT('global_cust_ctx',session_id_global);
      END clear_hr_context;
     END;
    /
    

    For a detailed explanation of how this type of package works,seeExample 6-12.

  2. Grant@H_404_173@EXECUTEprivileges on the@H_404_173@cust_ctx_pkgpackage to the connection pool owner,@H_404_173@apps_user.

    GRANT EXECUTE ON cust_ctx_pkg TO apps_user;
    

Step 4: Test the Global Application Context

At this stage,you are ready to explore how this global application context and session ID settings work.

  1. Log on to SQL*Plus as the connection pool owner,userapps_user.

    CONNECT apps_user
    Enter password: password
    
  2. When the connection pool user logs on,the application sets the client session identifier as follows:

    BEGIN
     sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
    END;
    /
    

    You can test and check the value of the client session identifier as follows:

    1. Connect to SQL*Plus as the connection pool userapps_user.

    2. Set the session ID:

      EXEC sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
      
    3. Check the session ID:

      SELECT SYS_CONTEXT('userenv','client_identifier') FROM dual;
      

      The following output should appear:

      SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')
      --------------------------------------------------
      34256
      
  3. As userEXEC sysadmin_ctx.cust_ctx_pkg.set_cust_ctx('Category','Gold Partner'); EXEC sysadmin_ctx.cust_ctx_pkg.set_cust_ctx('Benefit Level','Highest');

    (In a real-world scenario,the middle-tier application would set the global application context values,similar to how the client session identifier was set in Step2.)

  4. Enter the following@H_404_173@SELECT SYS_CONTEXTstatement to check that the settings were successful:

    col category format a13
    col benefit_level format a14
    
    SELECT SYS_CONTEXT('global_cust_ctx','Category') category,SYS_CONTEXT('global_cust_ctx','Benefit Level') benefit_level FROM dual;
    

    The following output should appear:

    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    Gold Partner   Highest
    

What@H_404_173@apps_userhas done here,within the client session 34256,is set a global application context on behalf of a nondatabase user. This context sets the@H_404_173@Categoryand@H_404_173@Benefit Level@H_404_173@DBMS_SESSION.SET_CONTEXT attributesto be@H_404_173@Gold Partnerand@H_404_173@Highest,respectively. The context exists only for user@H_404_173@apps_userwith client ID 34256. When a nondatabase user logs in,behind the scenes,he or she is really logging on as the connection pool user@H_404_173@apps_user. Hence,monospace; font-size:1em; white-space:pre">Highestcontext values are available to the nondatabase user.

Suppose the user had been a database user and could log in without using the intended application. (For example,the user logs in using sql*Plus.) Because the user has not logged in through the connection pool user404_173@apps_usersession. If the user runs the@H_404_173@SELECT SYS_CONTEXTstatement,the following output appears:

CATEGORY       BENEFIT_LEVEL
-------------  --------------

Next,try the following test:

  1. As userEXEC sysadmin_ctx.cust_ctx_pkg.clear_hr_session(34256);

  2. Check the global application context settings again.

    SELECT SYS_CONTEXT('global_cust_ctx','Benefit Level') benefit_level FROM dual;
    
    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    

    Because@H_404_173@apps_userhas cleared the session ID,the global application context settings are no longer available.

  3. Restore the session ID to 34256,and then check the context values.

    EXEC sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
    
    SELECT SYS_CONTEXT('global_cust_ctx','Benefit Level') benefit_level FROM dual;
    

    The following output should appear:

    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    Gold Partner   Highest
    

    As you can see,resetting the session ID to 34256 brings the application context values back again. To summarize,the global application context must be set onlyoncefor this user,but the client session ID must be seteach timethe user logs on.

  4. Now try clearing and then checking the global application context values.

    EXEC sysadmin_ctx.cust_ctx_pkg.clear_hr_context;
    
    SELECT SYS_CONTEXT('global_cust_ctx','Benefit Level') benefit_level FROM dual;
    

    The following output should appear:

    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    

    At this stage,the client session ID,34256 is still in place,but the application context settings no longer exist. This enables you to continue the session for this user but without using the prevIoUsly set application context values.

3个例子都提供了clear_hr_context 存储过程。这是因为global application context常驻SGA,需要用户使用完毕就清理,以免信息泄露。

Tutorial: Creating and Using a Database Session-Based Application Context

Step 1: Create User Accounts and Ensure the User SCOTT Is Active

  1. Log on as user@H_404_173@SYSand connect using the@H_404_173@AS SYSDBAprivilege.

    sqlplus sys as sysdba
    Enter password: password
    
  2. Create theGRANT CREATE SESSION,CREATE PROCEDURE,CREATE TRIGGER,ADMINISTER DATABASE TRIGGER TO sysadmin_ctx IDENTIFIED BY password; GRANT SELECT ON HR.EMPLOYEES TO sysadmin_ctx; GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;

    Replace"Minimum Requirements for Passwords"for more information.

  3. Create the following user account for Lisa Ozer,who is listed as having@H_404_173@lozerfor her email account in the@H_404_173@HR.EMPLOYEEStable.

    GRANT CREATE SESSION TO LOZER IDENTIFIED BY password;
    

    Replace"Minimum Requirements for Passwords"for more information.

  4. The sample user@H_404_173@SCOTTwill also be used in this tutorial,so query the@H_404_173@DBA_USERSdata dictionary view to ensure that@H_404_173@SCOTTis not locked or expired.

    SELECT USERNAME,ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME = 'SCOTT';
    

    If the@H_404_173@DBA_USERSview lists user@H_404_173@SCOTTas locked and expired,then enter the following statement to unlock the@H_404_173@SCOTTaccount and create a new password for him:

    ALTER USER SCOTT ACCOUNT UNLOCK IDENTIFIED BY password;
    

    Enter a password that is secure. For greater security,donotgive the@H_404_173@SCOTTaccount the same password from prevIoUs releases of Oracle Database. See"Minimum Requirements for Passwords"for the minimum requirements for creating passwords.

Step 2: Create the Database Session-Based Application Context

  1. Log on to SQL*Plus assysadmin_ctx.

    CONNECT sysadmin_ctx
    Enter password: password
    
  2. Create the application context using the following statement:

    CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg;
    

    Remember that even though usersysadmin_ctxhas created this application context,monospace; font-size:1em; white-space:pre">SYSschema owns the context.

Step 3: Create a Package to Retrieve Session Data and Set the Application Context

Example 6-7shows how to create the package you need to retrieve the session data and set the application context. Before creating the package,ensure that you are still logged on as user@H_404_173@sysadmin_ctx. (You can copy and paste this text by positioning the cursor at the start of@H_404_173@CREATE OR REPLACEin the first line.)

Example 6-7 Package to Retrieve Session Data and Set a Database Session Context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE OR REPLACE PACKAGE set_empno_ctx_pkg IS 
   PROCEDURE set_empno; 
 END; 
 /
 CREATE OR REPLACE PACKAGE BODY set_empno_ctx_pkg IS
   PROCEDURE set_empno 
   IS 
    emp_id HR.EMPLOYEES.EMPLOYEE_ID%TYPE;
   BEGIN 
    SELECT EMPLOYEE_ID INTO emp_id FROM HR.EMPLOYEES 
       WHERE email = SYS_CONTEXT('USERENV','SESSION_USER');
    DBMS_SESSION.SET_CONTEXT('empno_ctx','employee_id',emp_id);
   EXCEPTION  
    WHEN NO_DATA_FOUND THEN NULL;
  END;
 END;
/

This package creates a procedure called@H_404_173@set_empnothat performs the following actions:

  • Line 8:Declares a variable,monospace; font-size:1em; white-space:pre">emp_id,to store the employee ID for the user who logs on. It uses the same data type as the@H_404_173@EMPLOYEE_IDcolumn in@H_404_173@HR.EMPLOYEES.

  • Line 10:Performs a@H_404_173@SELECTstatement to copy the employee ID that is stored in the@H_404_173@employee_idcolumn data from the@H_404_173@HR.EMPLOYEEStable into the@H_404_173@emp_idvariable.

  • Line 11:Uses a@H_404_173@WHEREclause to find all employee IDs that match the email account for the session user. The@H_404_173@SYS_CONTEXTfunction uses the predefined@H_404_173@USERENVcontext to retrieve the user session ID,which is the same as the@H_404_173@emailcolumn data. For example,the user ID and email address for Lisa Ozer are both the same:@H_404_173@lozer.

  • Line 12:Uses the@H_404_173@DBMS_SESSION.SET_CONTEXTprocedure to set the application context:

    • @H_404_173@'empno_ctx': Calls the application context@H_404_173@empno_ctx. Enclose@H_404_173@empno_ctxin single quotes.

    • @H_404_173@'employee_id': Creates the attribute value of the@H_404_173@empno_ctxapplication context name-value pair,by naming it@H_404_173@employee_id. Enclose@H_404_173@employee_idin single quotes.

    • @H_404_173@emp_id: Sets the value for the@H_404_173@employee_idattribute to the value stored in the@H_404_173@emp_idvariable. The@H_404_173@emp_idvariable was created inLine 8and the employee ID was retrieved inLines 10–11.

    To summarize,monospace; font-size:1em; white-space:pre">set_empno_ctx_pkg.set_empnoprocedure says,"Get the session ID of the user and then match it with the employee ID and email address of any user listed in the@H_404_173@HR.EMPLOYEEStable."

  • Lines 13–14: Add a@H_404_173@WHEN NO_DATA_FOUNDsystem exception to catch any@H_404_173@no data founderrors that may result from the@H_404_173@SELECTstatement inLines 10–11. Without this exception,the package and logon trigger will work fine and set the application context as needed,but then any non-system administrator users other than the users listed in the@H_404_173@HR.EMPLOYEEStable will not be able to log in to the database. Other users should be able to log in to the database,assuming they are valid database users. Once the application context information is set,then you can use this session information as a way to control user access to a particular application.

Step 4: Create a Logon Trigger for the Package

As userCREATE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE BEGIN sysadmin_ctx.set_empno_ctx_pkg.set_empno; END; /

Step 5: Test the Application Context

  1. Log on as userlozer.

    CONNECT lozer
    Enter password: password
    

    When userlozerlogs on,monospace; font-size:1em; white-space:pre">empno_ctxapplication context collects her employee ID. You can check it as follows:

    SELECT SYS_CONTEXT('empno_ctx','employee_id') emp_id FROM DUAL;
    

    The following output should appear:

    EMP_ID
    --------------------------------------------------------
    168
    
  2. Log on as userSCOTT.

    CONNECT SCOTT
    Enter password: password
    

    UserSCOTTis not listed as an employee in theHR.EMPLOYEEStable,so theempno_ctxapplication context cannot collect an employee ID for him.

    SELECT SYS_CONTEXT('empno_ctx','employee_id') emp_id FROM DUAL;
    

    The following output should appear:

    EMP_ID
    --------------------------------------------------------
    

From here,the application can use the user session information to determine how much access the user can have in the database. You can use Oracle Virtual Private Database to accomplish this. SeeChapter 7,"Using Oracle Virtual Private Database toControlData Access,"for more information.

Step 6: Remove the Components for This Tutorial

  1. Log on as@H_404_173@AS SYSDBA.

    CONNECT SYS/AS SYSDBA
    Enter password: password
    
  2. Drop the users@H_404_173@sysadmin_ctxand@H_404_173@lozer:

    DROP USER sysadmin_ctx CASCADE;
    DROP USER lozer;
    
  3. Drop the application context.

    DROP CONTEXT empno_ctx;
    

    Remember that even though@H_404_173@sysadmin_ctxcreated the application context,it is owned by the@H_404_173@SYSschema.

  4. If you want,lock and expire@H_404_173@SCOTT,unless other users want to use this account:

    ALTER USER SCOTT PASSWORD EXPIRE ACCOUNT LOCK; 

猜你在找的Oracle相关文章