Oracle® Database Security Guide 11g Release 1 (11.1) Part Number B28531-01 |
|
|
View PDF |
An application context retrieves information about a user session and then stores this information in cache so that it is easily accessible during the user session. You can use this information as a basis on which to permit or prevent that user from accessing data.
This chapter discusses the following topics:
An application context is a name-value pair that enables an application to access session information about a user, such as the user ID or other user-specific information, or a client ID, and then securely pass this data to the database. You can then use this information to either permit or prevent the user from accessing data through the application.
The name-value pair can be summarized as follows:
Name: Refers to the name (called a namespace) of the application context. For example, a namespace for an application context that retrieves user data from an underlying order entry table could be called OE_CTX
.
Value: Refers to a value set by an attribute of the namespace. For example, for the OE_CTX
namespace, if you wanted to retrieve a customer ID from the order entry table, you could create an attribute called CUSTOMER_NUMBER
that can set the value for this ID.
Think of an application context as a global variable that holds information that is accessed during a database session. To set the values for the application context, you must create a PL/SQL package procedure. In fact, it is the only way that you can set application context values. The procedure assigns the values for the application context attributes at run time, not when you create the application context. Because the procedure, and not the user, assigns the values, it is a trusted procedure. This method enables you to better secure database access.
Oracle Database stores the application context values in a secure data cache available in the User Global Area (UGA) or the System (sometimes called "Shared") Global Area (SGA). This way, the application context values are retrieved during the session. Because the application context stores the values in this data cache, it increases performance for your applications. You can use an application context by itself, with Oracle Virtual Private Databases policies, or with other fine-grained access control policies. See "Using Oracle Virtual Private Database with an Application Context" if you are interested in using application contexts with Virtual Private Database policies.
Most applications contain the kind of information that can be used for application contexts. For example, in an order entry application that uses a table containing the columns ORDER_NUMBER
and CUSTOMER_NUMBER
, you can use the values in these columns as security attributes to restrict access by a customer to his or her own orders, based on the ID of that customer.
Application contexts are useful for the following purposes:
Enforcing fine-grained access control, for example, in Oracle Virtual Private Database polices
Preserving user identity across multitier environments
Enforcing stronger security for your applications, because the application context is controlled by a trusted procedure, not the user
Increasing performance by serving as a secure data cache for attributes needed by an application for fine-grained auditing or for use in PL/SQL conditional statements or loops
This cache saves the repeated overhead of querying the database each time these attributes are needed. Because the application context stores session data in cache rather than forcing your applications to retrieve this data repeatedly from a table, it greatly improves the performance of your applications.
Serving as a holding area for name-value pairs that an application can define, modify, and access
There are three general categories of application contexts:
Database session-based application contexts. This type retrieves data that is stored in the database user session (that is, the UGA) cache. There are three categories of database session-based application contexts:
Initialized locally. Initializes the application context locally, to the session of the user.
Initialized externally. Initializes the application context from an Oracle Call Interface (OCI) interface, a job queue process, or a connected user database link.
Initialized globally. Uses attributes and values from a centralized location, such as an LDAP directory.
"Using Database Session-Based Application Contexts" describes this type of application context.
Global application contexts. This type retrieves data that is stored in the System Global Area (SGA) so that it can be used for applications that use a sessionless model, such as middle-tier applications in a three-tiered architecture. A global application context is useful if the session context needs to be shared across sessions, for example, through connection pool implementations.
"Using Global Application Contexts" describes this type.
Client session-based application contexts. This type uses Oracle Call Interface functions on the client side to set the user session data, and then to perform the necessary security checks to restrict user access.
"Using Client Session-Based Application Contexts" describes this type.
Table 7-1 summarizes the different types of application contexts.
Table 7-1 Types of Application Contexts
Application Context Type | Stored in UGA | Stored in SGA | Supports Connected User Database Links | Supports Centralized Storage of Users' Application Context | Supports Sessionless Multitier Applications |
---|---|---|---|---|---|
Database session-based application context initialized locally |
Yes |
No |
No |
No |
No |
Database session-based application context initialized externally |
Yes |
No |
Yes |
No |
No |
Database session-based application context initialized globally |
Yes |
No |
No |
Yes |
No |
Global application context |
No |
Yes |
No |
No |
Yes |
Client session-based application context |
Yes |
No |
Yes |
No |
Yes |
This section explores the following topics:
Creating a PL/SQL Package to Set the Database Session-Based Application Context
Creating a Logon Trigger to Run a Database Session Application Context Package
Example of Creating and Using a Database Session-Based Application Context
Initializing Database Session-Based Application Contexts Externally
Initializing Database Session-Based Application Contexts Globally
Using Externalized Database Session-Based Application Contexts
If you need to retrieve session information for database users, use a database session-based application context. This type of application context uses a PL/SQL procedure within Oracle Database to retrieve, set, and secure the data it manages.
Note:
If your users are application users, that is, users who are not in your database, consider using a global application context instead. See "Using Global Application Contexts" for more information.The database session-based application context is managed entirely within Oracle Database. Oracle Database sets the values, and then when the user exits the session, automatically clears the application context values stored in cache. If the user connection ends abnormally, for example, during a power failure, then the PMON background process cleans up the application context data.You do not need to explicitly clear the application context from cache.
The advantage of having Oracle Database manage the application context is that you can centralize the application context management. Any application that accesses this database will need to use this application context to permit or prevent user access to that application. This provides benefits both in improved performance and stronger security.
You use the following components to create and use a database session-based application context:
The application context. You use the CREATE CONTEXT
SQL statement to create an application context. This statement names the application context (namespace) and associates it with a PL/SQL procedure that is designed to retrieve session data and set the application context.
A PL/SQL procedure to perform the data retrieval and set the context. "About the Package That Manages the Database Session-Based Application Context" describes the tasks this procedure must perform. Ideally, create this procedure within a package, so that you can include other procedures if you want, for example, to perform error checking tasks.
A way to set the application context when the user logs on. Users who log on to applications that use the application context must run a PL/SQL package that sets the application context. You can achieve this with either a logon trigger that fires each time the user logs on, or you can embed this functionality in your applications.
"Example of Creating and Using a Database Session-Based Application Context" shows how to create and use a database session-based application context that is initialized locally.
You can also initialize session-based application contexts either externally or globally. Either method stores the context information in the user session.
External initialization. This type can come from an OCI interface, a job queue process, or a connected user database link. See "Initializing Database Session-Based Application Contexts Externally" for detailed information.
Global initialization. This type uses attributes and values from a centralized location, such as an LDAP directory. "Initializing Database Session-Based Application Contexts Globally" provides more information.
To create a database session-based application context, you use the CREATE
CONTEXT
PL/SQL statement. Here, you create a namespace for the application context and then associate it with a PL/SQL package that manages the name-value pair that holds the session information of the user. You must have the CREATE ANY CONTEXT
system privilege to run this statement, and the DROP ANY CONTEXT
privilege to use the DROP CONTEXT
statement if you drop the application context. In a database session-based application context, data is stored in the database user session (UGA) in a namespace that you create with the CREATE CONTEXT
SQL statement.
Each application context must have a unique attribute and belong to a namespace. That is, context names must be unique within the database, not just within a schema.
The ownership of the application context is as follows: Even though a user who has been granted the CREATE ANY CONTEXT
and DROP ANY CONTEXT
privileges can create and drop the application context, it is owned by the SYS
schema. Oracle Database associates the context with the schema account that created it, but if you drop this user, the context still exists in the SYS
schema. As user SYS
, you can drop the application context.
Example 7-1 shows how to use CREATE CONTEXT
to create a database session-based application context:
Example 7-1 Creating a Database Session-Based Application Context
CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg;
Here, empno_ctx
is the context namespace and set_empno_ctx_pkg
is the package that sets attributes for the empno_ctx
namespace. When you create the application context, the PL/SQL package does not need to exist, but it must exist at run time. "Step 3: Create a Package to Retrieve Session Data and Set the Application Context" shows an example of how to create a package that can be used with this application context.
Notice that when you create the context, you do not set its name-value attributes in the CREATE CONTEXT
statement. Instead, you set these in the package that you associate with the application context. The reason you do this is to prevent a malicious user from changing the context attributes without proper attribute validation.
Note:
You cannot create a context calledCLIENTCONTEXT
. This word is reserved for use with client session-based application contexts. See "Using Client Session-Based Application Contexts" for more information about this type of application context.For each application, you can create an application context that has its own attributes. Suppose, for example, you have three applications: General Ledger, Order Entry, and Human Resources. You can specify different attributes for each application:
For the order entry application context, you can specify the attribute CUSTOMER_NUMBER.
For the general ledger application context, you can specify the attributes SET_OF_BOOKS
and TITLE.
For the human resources application context, you can specify the attributes ORGANIZATION_ID
, POSITION
, and COUNTRY
.
The data the attributes access is stored in the tables behind the applications. For example, the order entry application uses a table called OE.CUSTOMERS
, which contains the CUSTOMER_NUMBER
column, which provides data for the CUSTOMER_NUMBER
attribute. In each case, you can adapt the application context to your precise security needs.
This section describes the following topics:
The PL/SQL package, usually created in the schema of the security administrator, defines procedures that manage the session data represented by the application context. It must perform the following tasks:
Retrieve session information. To retrieve the user session information, you can use the SYS_CONTEXT
SQL function. The SYS_CONTEXT
function returns the value of parameter associated with the context namespace. You can use this function in both SQL and PL/SQL statements. Typically, you will use the built-in USERENV
namespace to retrieve the session information of a user.
Set the name-value attributes of the application context you created with CREATE CONTEXT. You can use the DBMS_SESSION.SET_CONTEXT
procedure to set the name-value attributes of the application context. The name-value attributes can hold information such as the user ID, IP address, authentication mode, the name of the application, and so on. The values of the attributes you set remain either until you reset them, or until the user ends the session.
Be executed by users. After you create the package, the user will need to execute the package when he or she logs on. You can create a logon trigger to execute the package automatically when the user logs on, or you can embed this functionality in your applications. Remember that the application context session values are cleared automatically when the user ends the session, so you do not need to manually remove the session data.
It is important to remember that the procedure is a trusted procedure: It is designed to prevent the user from setting his or her own application context attribute values. The user runs the procedure, but the procedure sets the application context values, not the user.
"Example of Creating and Using a Database Session-Based Application Context" shows how to create a database session-based application context.
The syntax for the PL/SQL function SYS_CONTEXT
is as follows:
SYS_CONTEXT ('namespace','parameter'[,length])
In this specification:
namespace
: The name of the application context. You can specify either a string or an expression.
parameter
: A parameter within the namespace
application context.
length
: Optional. The default maximum size of the return type is 256 bytes, but you can override the length by specifying a value up to 4000 bytes. Enter a value that is a NUMBER
data type, or a value that can be can be implicitly converted to NUMBER
. The data type of the SYS_CONTEXT
return type is a VARCHAR2
.
The SYS_CONTEXT
function provides a default namespace, USERENV
, which describes the current session of the user logged on. You can use SYS_CONTEXT
to retrieve different types of session-based information about a user, such as the user host computer ID, IP address, operating system user name, and so on. Remember that you only use USERENV
to retrieve session data, not set it. The predefined attributes are listed in the description for the SYS_CONTEXT
PL/SQL function in the Oracle Database SQL Language Reference.
For example, to retrieve the name of the host computer to which a client is connected, you can use the HOST
parameter of USERENV
as follows:
SYS_CONTEXT ('userenv','host')
You can check the SYS_CONTEXT
settings by issuing a SELECT
SQL statement on the DUAL
table. The DUAL
table is a small table in the data dictionary that Oracle Database and user-written programs can reference to guarantee a known result. This table has one column called DUMMY
and one row that contains the value X
.
Example 7-2 demonstrates how to find the host computer on which you are logged, assuming that you are logged on to the SHOBEEN_PC
host computer under EMP_USERS
.
During a session in which you expect a change in policy between executions of a given query, the query must use dynamic SQL. You must use dynamic SQL because static SQL and dynamic SQL parse statements differently:
Static SQL statements are parsed at compile time. They are not parsed again at execution time for performance reasons.
Dynamic SQL statements are parsed every time they are executed.
Consider a situation in which Policy A is in force when you compile a SQL statement, and then you switch to Policy B and run the statement. With static SQL, Policy A remains in force. Oracle Database parses the statement at compile time, but does not parse it again upon execution. With dynamic SQL, Oracle Database parses the statement upon execution, then the switch to Policy B takes effect.
For example, consider the following policy:
EMPLOYEE_NAME = SYS_CONTEXT ('USERENV', 'SESSION_USER')
The policy EMPLOYEE_NAME
matches the database user name. It is represented in the form of a SQL predicate in Oracle Virtual Private Database: the predicate is considered a policy. If the predicate changes, then the statement must be parsed again to produce the correct result.
If SYS_CONTEXT
is used inside a SQL function that is embedded in a parallel query, then the function includes the application context.
Consider a user-defined function within a SQL statement, which sets the user ID to 5:
CREATE FUNCTION set_id RETURN NUMBER IS BEGIN IF SYS_CONTEXT ('hr', 'id') = 5 THEN RETURN 1; ELSE RETURN 2; END IF; END;
Now consider the following statement:
SELECT * FROM emp WHERE set_id( ) = 1;
When this statement is run as a parallel query, the user session, which contains the application context information, is propagated to the parallel execution servers (query child processes).
When SQL statements within a user session involve database links, then Oracle Database runs the SYS_CONTEXT
SQL function at the host computer of the database link, and then captures the context information there (at the host computer).
If remote PL/SQL procedure calls are run on a database link, then Oracle Database runs any SYS_CONTEXT
function inside such a procedure at the destination database of the link. In this case, only externally initialized application contexts are available at the database link destination site. For security reasons, Oracle Database propagates only the externally initialized application context information to the destination site from the initiating database link site.
After you have used the SYS_CONTEXT function to retrieve the session data of a user, you are ready to set the application context values from the session of this user. To do so, use the DBMS_SESSION.SET_CONTEXT
procedure. (Ensure that you have EXECUTE
privileges for the DBMS_SESSION
PL/SQL package.)
Its syntax is as follows:
DBMS_SESSION.SET_CONTEXT ( namespace VARCHAR2, attribute VARCHAR2, value VARCHAR2, username VARCHAR2, client_id VARCHAR2);
In this specification:
namespace
: The namespace of the application context to be set, limited to 30 bytes. For example, if you were using a namespace called custno_ctx
, you would specify it as follows:
namespace => 'empno_ctx',
attribute
: The attribute of the application context to be set, limited to 30 bytes. For example, to create the ctx_attrib
attribute for the custno_ctx
namespace:
attribute => 'ctx_attrib',
value
: The value of the application context to be set, limited to 4000 bytes. Typically, this is the value retrieved by the SYS_CONTEXT
function and stored in a variable. For example:
value => ctx_value,
username
: Optional. The database user name attribute of the application context. The default is NULL
, which permits any user to access the session. For database session-based application contexts, omit this setting so that it uses the NULL
default.
The username
and client_id
parameters are used for globally accessed application contexts. See "Setting the username and client_id DBMS_SESSION.SET_CONTEXT Parameters" for more information.
client_id
: Optional. The application-specific client_id
attribute of the application context (64-byte maximum). The default is NULL
, which means that no client ID is specified. For database session-based application contexts, omit this setting so that it uses the NULL
default.
See Oracle Database PL/SQL Packages and Types Reference for detailed information about the DBMS_SESSION
package.
For example, remember the application context created in Example 7-1:
CREATE CONTEXT empno_ctx USING set_empno_ctx_proc;
Example 7-3 shows how to create a simple procedure that creates an attribute for the empno_ctx
application context.
Example 7-3 Simple Procedure to Create an Application Context Value
SQL> CREATE OR REPLACE PROCEDURE set_empno_ctx_proc( 2 emp_value IN VARCHAR2) 3 IS 4 BEGIN 5 DBMS_SESSION.SET_CONTEXT('empno_ctx', 'empno_attrib', emp_value); 6 END; 7 /
In this example:
Line 2: Takes emp_value
as the input parameter. This parameter specifies the value associated with the application context attribue empno_attrib
. Its limit is 4000 bytes.
Line 5: Sets the value of the application context by using the DBMS_SESSION.SET_CONTEXT
procedure:
'empno_ctx'
: Refers to the application context namespace. Enclose its name in single quotation marks.
'empno_attrib'
: Creates the attribute associated with the application context namespace.
ctx_value
: Specifies the value for the empno_attrib
attribute. Here, it refers to the ctx_value
parameter defined in Line 2.
At this stage, you can run the set_empno_ctx_proc
procedure to set the application context:
EXECUTE set_empno_ctx_proc ('42783');
(In a real world scenario, you would set the application context values in the procedure itself, so that it becomes a trusted procedure. This example is only used to show how data can be set for demonstration purposes.)
To check the application context setting, run the following SELECT
statement:
SELECT SYS_CONTEXT ('empno_ctx', 'empno_attrib') empno_attrib FROM DUAL; EMPNO_ATTRIB -------------- 42783
You can also query the SESSION_CONTEXT
data dictionary view to find all the application context settings in the current session of the database instance. For example:
SELECT * FROM SESSION_CONTEXT; NAMESPACE ATTRIBUTE VALUE -------------------------------------------------- EMPNO_CTX EMP_ID 42783
See Also:
"Example of Creating and Using a Database Session-Based Application Context" for how to create package that retrieves the user session information and then sets the application context based on this information
Oracle Database PL/SQL Packages and Types Reference for detailed information about the DBMS_SESSION.SET_CONTEXT
procedure
After you create the application context and its associated package, the user needs to run the package when he or she logs on. You can create a logon trigger that handles this automatically. You do not need to grant the user EXECUTE
permissions to run the package.
For example:
CREATE OR REPLACE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE BEGIN sec_mgr.set_empno_ctx_proc; END;
Remember that logon triggers may affect performance. In addition, test the logon trigger on a sample schema user first before creating it for the database. That way, if there is an error, you can easily correct it.
Be aware of situations in which if you have a changing set of books, or if positions change constantly. In these cases, the new attribute values may not be picked up right away, and you must force a cursor reparse to pick them up.
This example shows how to create an application context that limits logins only to anyone who has an e-mail account listed in the HR.EMPLOYEES
table. The e-mail account is the same as the user account name, so this is used as the basis on which to control user access.
You will follow these steps:
Step 1: Create User Accounts and Ensure the User SCOTT Is Active
Step 2: Create the Database Session-Based Application Context
Step 3: Create a Package to Retrieve Session Data and Set the Application Context
Log on as user SYS
and connect using the AS SYSDBA
privilege.
sqlplus "sys/as sysdba"
Enter password: password
Create the sysadmin_ctx
account, who will administer the database session-based application context.
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER TO sysadmin_ctx IDENTIFIED BY omni2all; GRANT SELECT ON hr.employees TO sysadmin_ctx; GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
Create the following user account for Lisa Ozer, who is listed as having lozer
for her e-mail account in the HR.EMPLOYEES
table.
GRANT CREATE SESSION TO lozer IDENTIFIED BY ready2go;
The sample user SCOTT
will also be used in this example, so query the DBA_USERS
data dictionary view to ensure that SCOTT
is not locked or expired.
SELECT USERNAME, ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME = 'SCOTT';
If the DBA_USERS
view lists user SCOTT
as locked and expired, then enter the following statement to unlock the SCOTT
account and create a new password for him:
ALTER USER SCOTT ACCOUNT UNLOCK IDENTIFIED BY tgris86d;
The password tgris86d
is offered as an example of a valid password, but you can create any password that is secure, according to the requirements described in "How Oracle Database Checks the Complexity of Passwords".
Log on to SQL*Plus as sysadmin_ctx
.
CONNECT sysadmin_ctx Enter password: omni2all
Create the application context using the following statement:
CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg;
Remember that even though user sysadmin_ctx
has created this application context, the SYS
schema owns the context.
Example 7-4 shows 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 sysadmin_ctx
, whose password is omni2all
.
Example 7-4 Package to Retrieve Session Data and Set a Database Session Context
SQL> CREATE OR REPLACE PACKAGE set_empno_ctx_pkg IS 2 PROCEDURE set_empno; 3 END; 4 / 5 CREATE OR REPLACE PACKAGE BODY set_empno_ctx_pkg IS 6 PROCEDURE set_empno 7 IS 8 emp_id NUMBER; 9 BEGIN 10 SELECT employee_id INTO emp_id FROM hr.employees 11 WHERE email = SYS_CONTEXT('USERENV', 'SESSION_USER'); 12 DBMS_SESSION.SET_CONTEXT('empno_ctx', 'employee_id', emp_id); 13 END; 14 END; 15 /
This package creates a procedure called SET_EMPNO
that performs the following actions:
Line 8: Declares a variable, emp_id
, to store the employee ID for the user who logs on.
Line 10: Performs a SELECT
statement to copy the employee ID that is stored in the employee_id
column data from the HR.EMPLOYEES
table into the emp_id
variable.
Line 11: Uses a WHERE
clause to find all employee IDs that match the e-mail account for the session user. The SYS_CONTEXT
function uses the predefined USERENV
context to retrieve the user session ID, which is the same as the email
column data. For example, the user ID and e-mail address for Lisa Ozer are both the same: lozer
.
Line 12: Uses the DBMS_SESSION.SET_CONTEXT
procedure to set the application context:
'empno_ctx'
: Calls the application context empno_ctx
. Enclose empno_ctx
in single quotes.
'employee_id'
: Creates the attribute value of the empno_ctx
application context name-value pair, by naming it employee_id
. Enclose employee_id
in single quotes.
emp_id
: Sets the value for the employee_id
attribute to the value stored in the emp_id
variable. The emp_id
variable was created in Line 8 and the employee ID was retrieved in Lines 10–11.
To summarize, the SET_EMPNO_CTX_PKG.SET_EMPNO
procedure says, "Get the session ID of the user, and then find the e-mail account name that matches this user ID. If there is a match, then let the user log on. If not, then deny the user access."
As user SYSADMIN_VPD
, create the following trigger:
CREATE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE BEGIN sysadmin_ctx.set_empno_ctx_pkg.set_empno; END; /
Log on as user lozer
.
CONNECT lozer Enter password: ready2go Connected.
As you can see, lozer
can log on, because she is listed in the HR.EMPLOYEES
table. In fact, any user who is listed in the HR.EMPLOYEES
table can log in.
Try to log on as user SCOTT
.
CONNECT SCOTT Enter password: tgris86d
User SCOTT
is not listed as an employee in the HR.EMPLOYEES
table, so he cannot log on. The application context that you created prevents him from doing so. The following error messages appear:
ORA-04088: error during execution of trigger 'SYS.SET_EMPNO_CTX_TRIG' ORA-01403: no data found ORA-06512: at "SYS.SET_EMPNO_CTX_PKG", line 6 ORA-06512: at line 2
However, users with administrative privileges are not affected by the application context, and can still log on.
Log on as SYS
and connect using AS SYSDBA
.
CONNECT SYS/AS SYSDBA
Enter password: password
Drop the users sysadmin_ctx
and lozer
:
DROP USER sysadmin_ctx CASCADE; DROP USER lozer CASCADE;
Drop the application context.
DROP CONTEXT empno_ctx;
Remember that even though sysadmin_ctx
created the application context, it is owned by the SYS
schema.
If you want, lock and expire SCOTT
, unless other users want to use this popular account:
ALTER USER SCOTT PASSWORD EXPIRE ACCOUNT LOCK;
After you have removed the application context and its associated package and trigger, users should be able to log on to the database instance again.
When you initialize a database session-based application context externally, you specify a special type of namespace that accepts the initialization of attribute values from external resources and then stores them in the local user session. Initializing an application context externally enhances performance because it is stored in the UGA and enables the automatic propagation of attributes from one session to another. Connected user database links are supported only by application contexts initialized from OCI-based external sources.
This section contains these topics:
Sometimes you need the default values from users. Initially, these default values may be hints or preferences, and then after validation, they become trusted contexts. Similarly, it may be more convenient for clients to initialize some default values, and then rely on a login event trigger or applications to validate the values.
For job queues, the job submission routine records the context being set at the time the job is submitted, and restores it when executing the batched job. To maintain the integrity of the context, job queues cannot bypass the designated PL/SQL package to set the context. Rather, the externally initialized application context accepts initialization of context values from the job queue process.
Automatic propagation of context to a remote session may create security problems. Developers or administrators can effectively handle the context that takes default values from resources other than the designated PL/SQL procedure by using logon triggers to reset the context when users log in.
You can create an application context that accepts the initialization of attributes and values through external resources. Examples include an OCI interface, a job queue process, or a database link.
Externally initialized application contexts provide the following features:
For remote sessions, automatic propagation of context values that are in the externally initialized application context namespace
For job queues, restoration of context values that are in the externally initialized application context namespace
For OCI interfaces, a mechanism to initialize context values that are in the externally initialized application context namespace
Although any client program that is using Oracle Call Interface can initialize this type of namespace, you can use login event triggers to verify the values. It is up to the application to interpret and trust the values of the attributes.
Example 7-5 shows how to create a database session-based application context that obtains values from an external source.
Middle-tier servers can initialize application context values on behalf of database users. Context attributes are propagated for the remote session at initialization time, and the remote database accepts the values if the namespace is externally initialized.
For example, a three-tier application creating lightweight user sessions through OCI or thick JDBC can access the PROXY_USER
attribute in USERENV
. This attribute enables you to determine if the user session was created by a middle-tier application. You could allow a user to access data only for connections where the user is proxied. If users connect directly to the database, then they would not be able to access any data.
You can use the PROXY_USER
attribute from the USERENV
namespace within Oracle Virtual Private Database to ensure that users only access data through a particular middle-tier application. For a different approach, you can develop a secure application role to enforce your policy that users access the database only through a specific proxy.
See Also:
"Preserving User Identity in Multitiered Environments" for information about proxy authentication and about using the USERENV
attribute CLIENT_IDENTIFIER
to preserve user identity across multiple tiers
"Using a Middle Tier Server for Proxy Authentication" for information about using a secure application role to enforce a policy through a specific proxy
You can use a centralized location to store the database session-based application context of the user. This enables applications to set up a user context during initialization based upon user identity. In particular, this feature supports Oracle Label Security labels and privileges. Initializing an application context globally makes it easier to manage contexts for large numbers of users and databases.
For example, many organizations want to manage user information centrally, in an LDAP-based directory. Enterprise User Security, a feature of Oracle Advanced Security, supports centralized user and authorization management in Oracle Internet Directory. However, there may be additional attributes an application needs to retrieve from Lightweight Directory Access Protocol (LDAP) to use for Oracle Virtual Private Database enforcement, such as the user title, organization, or physical location. Initializing an application context globally enables you to retrieve these types of attributes.
This section contains these topics:
How Globally Initialized Database Session-Based Application Contexts Work
Example of Initializing a Database Session-Based Application Context Globally
An application context that is initialized globally uses LDAP, a standard, extensible, and efficient directory access protocol. The LDAP directory stores a list of users to which this application is assigned. Oracle Database uses a directory service, typically Oracle Internet Directory, to authenticate and authorize enterprise users.
Note:
Enterprise User Security requires Oracle Advanced Security.
You can use third-party directories such as Microsoft Active Directory and Sun Microsystems SunONE as the directory service.
The orclDBApplicationContext
LDAP object (a subclass of groupOfUniqueNames
) stores the application context values in the directory. The location of the application context object is described in Figure 7-1, which is based on the Human Resources example.
On the LDAP side, an internal C function is required to retrieve the orclDBApplicationContext
value, which returns a list of application context values to the database. In this example, HR
is the namespace; Title and Project are the attributes; and Manager and Promotion are the values.
Figure 7-1 Location of Application Context in LDAP Directory Information Tree
To use a globally initialized secure application, you need to first configure Enterprise User Security, a feature of Oracle Advanced Security. Then, you set up the application context values for the user in the database and the directory.
When a global user (enterprise user) connects to the database, Enterprise User Security verifies the identity of the user connecting to the database. After authentication, the global user roles and application context are retrieved from the directory. When the user logs on to the database, the global roles and initial application context are already set.
See Also:
Oracle Database Enterprise User Security Administrator's Guide for information about configuring Enterprise User SecurityYou can configure and store the initial application context for a user, such as the department name and title, in the LDAP directory. The values are retrieved during user login so that the context is set properly. In addition, any information related to the user is retrieved and stored in the SYS_USER_DEFAULTS
application context namespace. The following procedure shows how this is accomplished:
Create the application context in the database.
CREATE CONTEXT hr USING hrapps.hr_manage_pkg INITIALIZED GLOBALLY;
Create and add new entries in the LDAP directory.
An example of the entries added to the LDAP directory follows. These entries create an attribute named Title
with the attribute value Manager
for the application (namespace) HR
, and assign user names user1
and user2
.
dn: cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US changetype: add cn: OracleDBAppContext objectclass: top objectclass: orclContainer dn: cn=hr,cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US changetype: add cn: hr objectclass: top objectclass: orclContainer dn: cn=Title,cn=hr, cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US changetype: add cn: Title objectclass: top objectclass: orclContainer dn: cn=Manager,cn=Title,cn=hr, cn=OracleDBAppContext,cn=myDomain,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US cn: Manager objectclass: top objectclass: groupofuniquenames objectclass: orclDBApplicationContext uniquemember: CN=user1,OU=Americas,O=Oracle,L=Redwoodshores,ST=CA,C=US uniquemember: CN=user2,OU=Americas,O=Oracle,L=Redwoodshores,ST=CA,C=US
If an LDAP inetOrgPerson
object entry exists for the user, then the connection retrieves the attributes from inetOrgPerson
, and assigns them to the namespace SYS_LDAP_USER_DEFAULT
. The following is an example of an inetOrgPerson
entry:
dn: cn=user1,ou=Americas,O=oracle,L=redwoodshores,ST=CA,C=US changetype: add objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: user1 sn: One givenName: User initials: UO title: manager, product development uid: uone mail: uone@us.oracle.com telephoneNumber: +1 650 123 4567 employeeNumber: 00001 employeeType: full time
Connect to the database.
When user1
connects to a database that belongs to the myDomain
domain, user1
will have his Title
set to Manager
. Any information related to user1
will be retrieved from the LDAP directory. The value can be obtained using the following syntax:
SYS_CONTEXT('namespace','attribute name')
For example:
DECLARE tmpstr1 VARCHAR2(30); tmpstr2 VARCHAR2(30); BEGIN tmpstr1 = SYS_CONTEXT('HR','TITLE); tmpstr2 = SYS_CONTEXT('SYS_LDAP_USER_DEFAULT','telephoneNumber'); DBMS_OUTPUT.PUT_LINE('Title is ' || tmpstr1); DBMS_OUTPUT.PUT_LINE('Telephone Number is ' || tmpstr2); END;
The output of this example is:
Title is Manager Telephone Number is +1 650 123 4567
Many applications store attributes used for fine-grained access control within a database metadata table. For example, an employees
table could include cost center, title, signing authority, and other information useful for fine-grained access control. Organizations also centralize user information for user management and access control in LDAP-based directories, such as Oracle Internet Directory. Application context attributes can be stored in Oracle Internet Directory, and assigned to one or more enterprise users. They can also be retrieved automatically upon login for an enterprise user, and then used to initialize an application context.
Note:
Enterprise User Security is a feature of Oracle Advanced Security.See Also:
"Initializing Database Session-Based Application Contexts Externally" for information about initializing local application context through external resources such as an OCI interface, a job queue process, or a database link
"Initializing Database Session-Based Application Contexts Globally" for information about initializing local application context through a centralized resource, such as Oracle Internet Directory
Oracle Database Enterprise User Security Administrator's Guide for information about enterprise users
This section explores the following topics:
Creating a PL/SQL Package to Manage a Global Application Context
Embedding Calls in Middle-Tier Applications to Manage the Client Session ID
Example of Creating a Global Application Context That Uses a Client Session ID
A global application context enables application context values to be accessible across database sessions. Oracle Database stores the global application context information in the System (sometimes called "Shared") Global Area (SGA) so that it can be used for applications that use a sessionless model, such as middle-tier applications in a three-tiered architecture. These applications cannot use a session-based application context because users authenticate to the application, and then it typically connects to the database as a single identity. Oracle Database initializes the global application context once, rather than for each user session. This improves performance, because connections are reused from a connection pool.
There are three general uses for global application contexts:
You need to share application values globally for all database users. For example, you may need to disable access to an application based on a specific situation. In this case, the values the application context sets are not user-specific, nor are they based on the private data of a user. The application context defines a situation, for example, to indicate the version of application module that is running.
You have database users who need to move from one application to another. In this case, the second application the user is moving to has different access requirements from the first application.
You need to authenticate nondatabase users, that is, users who are not known to the database. This type of user typically connects through a Web application by using a connection pool. These types of applications connect users to the database as single user, using the One Big Application User model. To authenticate this type of user, you use the client session ID of the user.
A global application context has the following components:
The global application context. You use the CREATE CONTEXT
SQL statement to create the global application context, and include the ACCESSED GLOBALLY
clause in the statement. This statement names the application context and associates it with a PL/SQL procedure that is designed to set the application data context data. The global application context is created and stored in the database schema of the security administrator who creates it.
A PL/SQL package to set the attributes. The package must contain a procedure that uses the DBMS_SESSION.SET_CONTEXT
procedure to set the global application context. The SET_CONTEXT
procedure provides parameters that enable you to create a global application context that fits any of the three user situations described in this section. You create, store, and run the PL/SQL package on the database server. Typically, it belongs in the schema of the security administrator who created it.
A middle-tier application to get and set the client session ID. For nondatabase users, which require a client session ID to be authenticated, you can use the Oracle Call Interface (OCI) calls in the middle-tier application to retrieve and set their session data. You can also use the DBMS_SESSION.SET_IDENTIFIER
procedure to set the client session ID.
To create a global application context, use the CREATE CONTEXT
SQL statement to create the application context and include the ACCESSED GLOBALLY
clause in the statement. You must have the CREATE ANY CONTEXT
system privilege before you can use the CREATE CONTEXT
statement, and the DROP ANY CONTEXT
privilege before you can drop the context with the DROP CONTEXT
statement. As with local application contexts, the global application context is created and stored in the database schema of a security administrator.
The ownership of the global application context is as follows: Even though a user who has been granted the CREATE ANY CONTEXT
and DROP ANY CONTEXT
privileges can create and drop the global application context, it is owned by the SYS
schema. Oracle Database associates the context with the schema account that created it, but if you drop this user, the context still exists in the SYS
schema. As user SYS
, you can drop the application context.
Example 7-6 shows how to create the global application context global_hr_ctx
, which is set by the hr_ctx_pkg
package.
This section includes the following topics:
About the Package That Manages the Global Application Context
Setting the username and client_id DBMS_SESSION.SET_CONTEXT Parameters
Sharing Global Application Context Values for All Database Users
Setting a Global Context for Database Users Who Move Between Applications
For detailed information about the DBMS_SESSION
package, see Oracle Database PL/SQL Packages and Types Reference.
The task of the PL/SQL package that you associate with a global application context is to use the DBMS_SESSION
package to set and clear the global application context values. You must have EXECUTE
privileges for the DBMS_SESSION
package before you use its procedures. Typically, you create and store this package in the database schema of a security administrator. The SYS
schema owns the DBMS_SESSION
package.
Unlike PL/SQL packages used to set a local application context, you do not include a SYS_CONTEXT
function to get the user session data. You do not need to include this function because the owner of the session, recorded in the USERENV
context, is the same for every user who is connecting.
You can run the procedures within the PL/SQL package for a global application context at any time. You do not need to create logon and logoff triggers to execute the package procedures associated with the global application context. A common practice is to run the package procedures from within the database application. Additionally, for nondatabase users, you use middle-tier applications to get and set client session IDs.
In addition to the namespace
, attribute
, and value
parameters, the DBMS_SESSION.SYS_CONTEXT
procedure provides the client_id
and username
parameters. Use these settings for global application contexts. Table 7-2 explains how the combination of these settings controls the type of global application context you can create.
Table 7-2 Setting the DBMS_SESSION.SET_CONTEXT username and client_id Parameters
Combination Settings | Result |
---|---|
|
This combination enables all users to access the application context. See "Sharing Global Application Context Values for All Database Users" for more information. These settings are also used for database session-based application contexts. See "Using Database Session-Based Application Contexts" for more information. |
|
This combination enables an application context to be accessed by multiple sessions, as long as the |
|
This combination enables an application to be accessed by multiple user sessions, as long as the |
|
This combination enables the following two scenarios:
Setting the See "Setting a Global Application Context for Nondatabase Users" for more information. |
To share global application values for all database users, set the namespace
, attribute
, and value
parameters in the SET_CONTEXT
procedure. In this scenario, all users who have database accounts will potentially have access to data in the database.
Example 7-7 shows how to create a package that sets and clears this type of global application context.
Example 7-7 Package to Manage Global Application Values for All Database Users
SQL> CREATE OR REPLACE PACKAGE hr_ctx_pkg 2 AS 3 PROCEDURE set_hr_ctx(sec_level IN VARCHAR2); 4 PROCEDURE clear_context; 5 END; 6 / 7 CREATE OR REPLACE PACKAGE BODY hr_ctx_pkg 8 AS 9 PROCEDURE set_hr_ctx(sec_level IN VARCHAR2) 10 AS 11 BEGIN 12 DBMS_SESSION.SET_CONTEXT( 13 namespace => 'global_hr_ctx', 14 attribute => 'job_role', 15 value => sec_level); 16 END set_hr_ctx; 17 18 PROCEDURE clear_context 19 AS 20 BEGIN 21 DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx'); 22 END clear_context; 23 END; 24 /
In this example:
Lines 12–16: Uses the DBMS_SESSION.SET_CONTEXT
procedure to set values for the namespace
, attribute
, and value
parameters. The sec_level
value is specified when the database application runs the hr_ctx_pkg.set_hr_ctx
procedure.
The username
and client_id
values are not set, hence, they are NULL
. This enables all users (database users) to have access to the values, which is appropriate for server-wide settings.
Line 13: In the SET_CONTEXT
procedure, sets the namespace
to global_hr_ctx
.
Line 14: Creates the job_role
attribute.
Line 15: Sets the value for the job_role
attribute to sec_level
.
Lines 18–22: Creates the clear_context
procedure to clear the context values. See "Clearing Session Data When the Session Closes" for more information.
Typically, you execute this procedure within a database application. For example, if all users logging in are clerks, and you want to use "clerk" as a security level, you would embed a call within a database application similar to the following:
BEGIN hr_ctx_pkg.set_hr_ctx('clerk'); END;
If the procedure successfully completes, you can check the application context setting as follows:
SELECT SYS_CONTEXT('global_hr_ctx', 'job_role') job_role FROM DUAL; JOB_ROLE ----------- clerk
To clear this application context, enter the following:
BEGIN hr_ctx_pkg.clear_context; END;
To check that it is really cleared, the following SELECT
statement should return no values:
SELECT SYS_CONTEXT('global_hr_ctx', 'job_role') job_role FROM DUAL; JOB_ROLE -----------
Note:
If Oracle Database returns error messages saying that you have insufficient privileges, ensure that you have correctly created the global application context. You should also query theDBA_CONTEXT
database view to ensure that your settings are correct, for example, that you are calling the procedure from the schema in which you created it.
If NULL
is returned, then you may have inadvertently set a client identifier. To clear the client identifier, run the following procedure:
EXEC DBMS_SESSION.CLEAR_IDENTIFIER;
To set a global application context for database users who move from one application to another, particularly when the applications have different access requirements, include the username
parameter in the SET_CONTEXT
procedure. This parameter specifies that the same schema be used for all sessions.
Use the following SET_CONTEXT
parameters:
namespace
attribute
value
username
Oracle Database matches the username
value so that the other application can recognize the application context. This enables the user to move between applications.
By omitting the client_id
setting, its value is NULL
, the default. This means that values can be seen by multiple sessions if the username
setting is the same for a database user who maintains the same context in different applications. For example, you can have a suite of applications that control user access with Oracle Virtual Private Database policies, with each user restricted to a job role.
Example 7-8 demonstrates how to set the username
parameter so that a specific user can move between applications. This example is similar to the package that was created in Example 7-7. The use of the username
parameter is indicated in bold typeface.
Example 7-8 Package to Manage Global Application Context Values for a User Moving Between Applications
CREATE OR REPLACE PACKAGE hr_ctx_pkg AS PROCEDURE set_hr_ctx(sec_level IN VARCHAR2, user_name IN VARCHAR2); PROCEDURE clear_context; END; / CREATE OR REPLACE PACKAGE BODY hr_ctx_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_role', value => sec_level, username => user_name); END set_hr_ctx; PROCEDURE clear_context AS BEGIN DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx'); END clear_context; END; /
Typically, you execute this procedure within a database application by embedding a call similar to the following example. Ensure that the value for the user_name
parameter (scott
in this case) is a valid database user name.
BEGIN hr_ctx_pkg.set_hr_ctx('clerk', 'scott'); END;
A secure way to manage this type of global application context is within your applications, embed code to grant a secure application role to the user. This code should include EXECUTE
permissions on the trusted PL/SQL package that sets the application context. In other words, the application, not the user, will set the context for the user.
When a nondatabase user, that is, a user who is not known to the database (such as a Web application user), starts a client session, the application server generates a client session ID. Once this ID is set on the application server, it needs to be passed to the database server side. You do this by using the DBMS_SESSION.SET_IDENTIFIER procedure to set the client session ID. To set the context, you set the client_id
parameter in the DBMS_SESSION.SET_CONTEXT
procedure, in a PL/SQL procedure on the server side. This enables you to manage the application context globally, yet each client sees only his or her assigned application context.
The client_id
value is the key here to getting and setting the correct attributes for the global application context. Remember that the client identifier is controlled by the middle-tier application, and once set, it remains open until it is cleared.
A typical way to manage this type of application context is to place the session_id
(client_identifier
) in a cookie, and send it to the end user's HTML page so that is returned on the next request. A lookup table in the application should also keep client identifiers so that they are prevented from being reused for other users and to implement an end-user session time out.
For nondatabase users, configure the following SET_CONTEXT
parameters:
namespace
attribute
value
username
client_id
Example 7-9 shows how to create a package that manages this type of global application context.
Example 7-9 Package to Manage Global Application Context Values for Nondatabase Users
SQL> CREATE OR REPLACE PACKAGE hr_ctx_pkg 2 AS 3 PROCEDURE set_session_id(session_id_p IN NUMBER); 4 PROCEDURE set_hr_ctx(sec_level_attr IN VARCHAR2, sec_level_val IN VARCHAR2); 5 PROCEDURE clear_session(session_id_p IN NUMBER); 6 PROCEDURE clear_context; 7 END; 8 / 9 CREATE OR REPLACE PACKAGE BODY hr_ctx_pkg 10 AS 11 session_id_global NUMBER; 12 PROCEDURE set_session_id(session_id_p IN NUMBER) 13 AS 14 BEGIN 15 session_id_global := session_id_p; 16 DBMS_SESSION.SET_IDENTIFIER(session_id_p); 17 END set_session_id; 18 19 PROCEDURE set_hr_ctx(sec_level_attr IN VARCHAR2, sec_level_val IN VARCHAR2) 20 AS 21 BEGIN 22 DBMS_SESSION.SET_CONTEXT( 23 namespace => 'global_hr_ctx', 24 attribute => sec_level_attr, 25 value => sec_level_val, 26 username => USER, 27 client_id => session_id_global); 28 END set_hr_ctx; 29 30 PROCEDURE clear_session(session_id_p IN NUMBER) 31 AS 32 BEGIN 33 DBMS_SESSION.SET_IDENTIFIER(session_id_p); 34 DBMS_SESSION.CLEAR_IDENTIFIER; 35 END clear_session; 36 37 PROCEDURE clear_context 38 AS 39 BEGIN 40 DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx', session_id_global); 41 END clear_context; 42 END; 43 /
In this example:
Line 11: Creates the session_id_global
variable, which will hold the client session ID. The session_id_global
variable is referenced throughout the package definition, including the procedure that creates the global application context attributes and assigns them values. This means that the global application context values will always be associated with this particular session ID.
Lines 12–17: Creates the set_session_id
procedure, which writes the client session ID to the session_id_global
variable.
Lines 19–28: Creates the set_hr_ctx
procedure, which creates global application context attributes and enables you to assign values to these attributes. Within this procedure:
Line 26: Specifies the username
value. This example sets it by calling the Oracle Database-supplied USER
function, which adds the session owner from the context retrieval process. The USER
function ensures that only the user who set the application context can access the context. See Oracle Database SQL Language Reference for more information about the USER
function.
If you had specified NULL
(the default for the username
parameter), then any user can access the context.
Setting both the username
and client_id
values enables two scenarios. For lightweight users, set the username
parameter to a connection pool owner (for example, APPS_USER
), and then set client_id
to the client session ID. If you want to use a stateless Web session, set the user_name
parameter to the same database user who has logged in, and ensure that this user keeps the same client session ID. See "Setting the username and client_id DBMS_SESSION.SET_CONTEXT Parameters" for an explanation of how different username
and client_id
settings work.
Line 27: Specifies client_id
value. This example sets it to the session_id_global
variable. This associates the context settings defined here with a specific client session ID, that is, the one that is set when you run the set_session_id
procedure. If you specify the client_id
parameter default, NULL
, then the global application context settings could be used by any session.
Lines 30–35: Creates the clear_session
procedure to clear the client session identifier. Line 33 sets it to ensure that you are clearing the correct session ID, that is, the one stored in variable session_id_p defined in Line 10.
Lines 37–42: Creates the clear_context
procedure, so that you can clear the context settings for the current user session, which were defined by the global_hr_ctx
variable. See "Clearing Session Data When the Session Closes" for more information.
See Also:
"Example of Creating a Global Application Context That Uses a Client Session ID" for a tutorial that demonstrates how a global application context used for client session IDs works
"Setting the Client Session ID Using a Middle-Tier Application"
"Using Client Identifiers to Identify Application Users Not Known to the Database" for information about how client identifiers work on middle-tier systems
The application context exists entirely within memory. When the user exits a session, you need to clear the context for the client_identifier
value. This releases memory and prevents other users from accidentally using any left over values.
To clear session data when a user exits a session, use either of the following methods in the server-side PL/SQL package:
Clearing the client identifier when a user exits a session. Use the DBMS_SESSION.CLEAR_IDENTIFIER
procedure. For example:
DBMS_SESSION.CLEAR_IDENTIFIER;
Continuing the session but still clearing the context. If you want the session to continue, but you still need to clear the context, use the DBMS_SESSION.CLEAR_CONTEXT
or the DBMS_SESSION.CLEAR_ALL_CONTEXT
procedure. For example:
DBMS_SESSION.CLEAR_CONTEXT(namespace, client_identifier, attribute);
The CLEAR_CONTEXT
procedure clears the context for the current user. To clear the context values for all users, for example, when you need to shut down the application server, use the CLEAR_ALL_CONTEXT
procedure.
Global application context values are available until they are cleared, so you should use CLEAR_CONTEXT
or CLEAR_ALL_CONTEXT
to ensure that other sessions do not have access to these values.
This section includes the following topics:
About Managing Client Session IDs Using a Middle-Tier Application
Retrieving the Client Session ID Using a Middle-Tier Application
Setting the Client Session ID Using a Middle-Tier Application
The application server generates the client session ID. From a middle-tier application, you can get, set, and clear the client session IDs. To do so, embed either Oracle Call Interface (OCI) calls or DBMS_SESSION
PL/SQL package procedures into the middle-tier application code.
The application authenticates the user, sets the client identifier, and sets it in the current session. The PL/SQL package SET_CONTEXT
sets the client_identifier
value in the application context. See "Setting a Global Application Context for Nondatabase Users" for more information.
When a user starts a client session, the application server generates a client session ID. To retrieve this client ID, you can use the OCIStmtExecute
call with any of the following statements:
SELECT SYS_CONTEXT('userenv', 'client_identifier') FROM dual; SELECT CLIENT_IDENTIFIER from V$SESSION; SELECT value FROM session_context WHERE attribute='CLIENT_IDENTIFIER';
Example 7-10 shows how to use the OCIStmtExecute
call to retrieve a client session ID value.
Example 7-10 Using OCIStmtExecute to Retrieve a Client Session ID Value
1 oratext clientid[31]; 2 OCIDefine *defnp1 = (OCIDefine *) 0; 3 OCIStmt *statementhndle; 4 oratext *selcid = (oratext *)"SELECT SYS_CONTEXT('userenv', 5 'client_identifier') FROM DUAL"; 6 7 OCIStmtPrepare(statementhndle, errhp, selcid, (ub4) strlen((char *) selcid), 8 (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); 9 10 OCIDefineByPos(statementhndle, &defnp1, errhp, 1, (dvoid *)clientid, 31, 11 SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT); 12 13 OCIStmtExecute(servhndle, statementhndle, errhp, (ub4) 1, (ub4) 0, 14 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT); 15 16 printf("CLIENT_IDENTIFIER = %s \n", clientid);
In this example:
Lines 1–5: Create variables to store the client session ID, reference call for OCIDefine
, the statement handle, and the SELECT
statement to use.
Lines 7–8: Prepare the statement selcid
for execution.
Lines 10–11: Define the output variable clientid
for client session ID.
Lines 13–14: Execute the statement in the selcid
variable.
Line 16: Prints the formatted output for the retrieved client session ID.
After you use the OCIStmtExecute
call to retrieve the client session ID, you are ready to set this ID. The DBMS_SESSION.SET_CONTEXT
procedure in the server-side PL/SQL package then sets this session ID and optionally, overwrites the application context values.
Ensure that the middle-tier application code checks that the client session ID value (for example, the value written to user_id
in the previous examples) matches the client_id
setting defined in the server-side DBMS_SESSION.SET_CONTEXT
procedure. The sequence of calls on the application server side should be as follows:
Get the current client session ID. The session should already have this ID, but it is safer to ensure that it truly has the correct value.
Clear the current client session ID. This prepares the application to service a request from a different end user.
Set the new client session ID or the client session ID that has been assigned to the end user. This ensures that the session is using a different set of global application context values.
You can use the following methods to set the client session ID on the application server side:
Oracle Call Interface. Set the OCI_ATTR_CLIENT_IDENTIFIER
attribute in an OCIAttrSet
OCI call. This attribute sets the client identifier in the session handle to track the end user identity.
The following example shows how to use OCIAttrSet
with the ATTR_CLIENT_IDENTIFIER
parameter. The user_id
setting refers to a variable that stores the ID of the user who is logging on.
OCIAttrSet((void *)session_handle, (ub4) OCI_HTYPE_SESSION, (void *) user_id, (ub4)strlen(user_id), OCI_ATTR_CLIENT_IDENTIFIER, error_handle);
DBMS_SESSION package. Use the DBMS_SESSION.SET_IDENTIFIER
procedure to set the client identifier for the global application context. For example, assuming you are storing the ID of the user logging on in a variable called user_id
, you would enter the following line into the middle-tier application code:
DBMS_SESSION.SET_IDENTIFIER(user_id);
Note:
When the application generates a session ID for use as aCLIENT_IDENTIFIER
, then the session ID must be suitably random and protected over the network by encryption. If the session ID is not random, then a malicious user could guess the session ID and access the data of another user. If the session ID is not encrypted over the network, then a malicious user could retrieve the session ID and access the connection.
You can encrypt the session ID by using Oracle Advanced Security. See Oracle Database Advanced Security Administrator's Guide for more information. To learn more about encrypting data over a network, see Oracle Database 2 Day + Security Guide.
For both OCIAttrSet
and DBMS_SESSION.SET_IDENTIFIER
, you can check the value of this identifier as follows:
SELECT SYS_CONTEXT('userenv', 'client_identifier') FROM dual;
Another way to check this value is to query the V$SESSION
view:
SELECT CLIENT_IDENTIFIER from V$SESSION;
The application context exists entirely within memory. When the user exits a session, you need to clear the context for the client_identifier
value. This releases memory and prevents other users from accidentally using any left over values
To clear session data when a user exits a session, use either of the following methods in the middle-tier application code:
Clearing the client identifier when a user exits a session. Use the DBMS_SESSION.CLEAR_IDENTIFIER
procedure. For example:
DBMS_SESSION.CLEAR_IDENTIFIER;
Continuing the session but still clearing the context. If you want the session to continue, but you still need to clear the context, use the DBMS_SESSION.CLEAR_CONTEXT
or the DBMS_SESSION.CLEAR_ALL_CONTEXT
procedure. For example:
DBMS_SESSION.CLEAR_CONTEXT(namespace, client_identifier, attribute);
The CLEAR_CONTEXT
procedure clears the context for the current user. To clear the context values for all users, for example, when you need to shut down the application server, use the CLEAR_ALL_CONTEXT
procedure.
Global application context values are available until they are cleared, so you should use CLEAR_CONTEXT
or CLEAR_ALL_CONTEXT
to ensure that other sessions do not have access to these values.
This example shows how to create a global application context that uses a client session ID for a lightweight user application. It demonstrates how to control user access by using a connection pool.
Follow these steps:
You need to 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.
Follow these steps:
Log on to SQL*Plus as SYS
and connect using AS SYSDBA
.
sqlplus SYS/AS SYSDBA
Enter password: password
Create the sysadmin_ctx
account, who will administer the global application context.
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE TO sysadmin_ctx IDENTIFIED BY omni2all; GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
Create the account apps_user
, who will own the connection pool.
GRANT CREATE SESSION TO apps_user IDENTIFIED BY ready2go;
Log on as the security administrator sysadmin_ctx
.
CONNECT sysadmin_ctx Enter password: omni2all
Create the cust_ctx
global application context.
CREATE CONTEXT global_cust_ctx USING cust_ctx_pkg ACCESSED GLOBALLY;
The cust_ctx
context is created and associated with the schema of the security administrator sysadmin_ctx
. However, the SYS
schema owns the application context.
As sysadmin_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_session(session_id_p IN NUMBER);
PROCEDURE clear_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_session(session_id_p IN NUMBER)
AS
BEGIN
DBMS_SESSION.SET_IDENTIFIER(session_id_p);
DBMS_SESSION.CLEAR_IDENTIFIER;
END clear_session;
PROCEDURE clear_context
AS
BEGIN
DBMS_SESSION.CLEAR_CONTEXT('global_cust_ctx', session_id_global);
END clear_context;
END;
/
For a detailed explanation of how this type of package works, see Example 7-9.
Grant EXECUTE
privileges on the cust_ctx_pkg
package to the connection pool owner, apps_user
.
GRANT EXECUTE ON cust_ctx_pkg TO apps_user;
At this stage, you are ready to explore how this global application context and session ID settings work.
Log on to SQL*Plus as the connection pool owner, user apps_user
.
CONNECT apps_user Enter password: ready2go
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:
Log on as the connection pool user apps_user
.
Set the session ID:
EXEC sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
Check the session ID:
SELECT SYS_CONTEXT('userenv', 'client_identifier') FROM dual; SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') -------------------------------------------------- 34256
As user apps_user
, set the global application context as follows:
EXEC 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 Step 2.)
Enter the following SELECT SYS_CONTEXT
statement 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; CATEGORY BENEFIT_LEVEL ------------- -------------- Gold Partner Highest
What apps_user
has done here, within the client session 34256, is set a global application context on behalf of a nondatabase user. This context sets the Category
and Benefit Level
DBMS_SESSION.SET_CONTEXT attributes
to be Gold Partner
and Highest
, respectively. The context exists only for user apps_user
with client ID 34256. When a nondatabase user logs in, behind the scenes, he or she is really logging on as the connection pool user apps_user
. Hence, the Gold Partner
and Highest
context 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 user apps_user
, the global application context appears empty to our errant user. This is because the context was created and set under the apps_user
session. If the user runs the SELECT SYS_CONTEXT
statement, the following output appears:
CATEGORY BENEFIT_LEVEL ------------- --------------
Next, try the following test:
As user apps_user
, clear the session ID.
EXEC sysadmin_ctx.cust_ctx_pkg.clear_session(34256);
Check the global application context settings again.
SELECT SYS_CONTEXT('global_cust_ctx', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM dual; CATEGORY BENEFIT_LEVEL ------------- --------------
Because apps_user
has cleared the session ID, the global application context settings are no longer available.
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', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM dual; 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 needs to be set only once for this user, but the client session ID needs to be set each time the user logs on.
Now try clearing and then checking the global application context values.
EXEC sysadmin_ctx.cust_ctx_pkg.clear_context; SELECT SYS_CONTEXT('global_cust_ctx', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM dual; 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.
Log on as SYS
and connect using AS SYSDBA
.
CONNECT SYS/AS SYSDBA
Enter password: password
Drop the global application context.
DROP CONTEXT global_cust_ctx;
Remember that even though sysadmin_ctx
created the global application context, it is owned by the SYS
schema.
Drop the two sample users.
DROP USER sysadmin_ctx CASCADE; DROP USER apps_user;
This section provides two examples of how a global application context can be processed.
Consider the application server, AppSvr
, that has assigned the client identifier 12345
to client scott
. The AppSvr
application uses the scott
user to create a session (that is, it is not a connection pool.) The value assigned to the context attribute can come from anywhere, for example, from running a SELECT
statement on a table that holds the responsibility codes for users. When the application context is populated, it is stored in memory. As a result, any action that needs the responsibility code can access it quickly with SYS_CONTEXT
call, without the overhead of accessing a table. The only advantage of a global context over a local context in this case is if scott
were changing applications frequently and used the same context in each application.
The following steps show how the global application context process sets the client identifier for scott
.
The administrator creates a global context namespace by using the following statement:
CREATE OR REPLACE CONTEXT hr USING hr.init ACCESSED GLOBALLY;
The administrator creates a PL/SQL package for the HR application context to indicate that, for this client identifier, there is an application context called responsibility
with a value of 13
in the HR
namespace.:
CREATE OR REPLACE PROCEDURE hr.init AS BEGIN DBMS_SESSION.SET_CONTEXT( namespace => 'HR', attribute => 'RESPONSIBILITY', value => '13', username => 'SCOTT', client_id => '12345' ); END;
This PL/SQL procedure is stored in the HR
database schema, but typically it is stored in the schema of the security administrator.
The AppSvr application issues the following command to indicate the connecting client identity each time scott
uses AppSvr
to connect to the database:
DBMS_SESSION.SET_IDENTIFIER('12345');
When there is a SYS_CONTEXT('HR','RESPONSIBILITY')
call within the database session, the database matches the client identifier, 12345
, to the global context, and then returns the value 13
.
When exiting this database session, AppSvr
clears the client identifier by issuing the following procedure:
DBMS_SESSION.CLEAR_IDENTIFIER( );
To release the memory used by the application context, AppSvr
issues the following procedure:
DBMS_SESSION.CLEAR_CONTEXT( );
CLEAR_CONTEXT
is needed when the user session is no longer active, either on an explicit logout, timeout, or other conditions determined by the AppSvr
application.
Note:
After a client identifier in a session is cleared, it becomes aNULL
value. This implies that subsequent SYS_CONTEXT
calls only retrieve application contexts with NULL
client identifiers, until the client identifier is set again using the SET_IDENTIFIER
interface.The following steps show the global application context process for a lightweight user application. The lightweight user, robert
, is not known to the database through the application.
The administrator creates the global context namespace by using the following statement:
CREATE CONTEXT hr USING hr.init ACCESSED GLOBALLY;
The HR
application server, AppSvr
, starts and then establishes multiple connections to the HR
database as the appsmgr
user.
User SCOTT
logs in to the HR
application server.
AppSvr
authenticates robert
to the application.
AppSvr
assigns a temporary session ID (or uses the application user ID), 12345
, for this connection.
The session ID is returned to the browser used by robert
as part of a cookie or is maintained by AppSvr
.
AppSvr
initializes the application context for this client by calling the hr.init
package, which issues the following statements:
DBMS_SESSION.SET_CONTEXT( 'hr', 'id', 'robert', 'APPSMGR', 12345 ); DBMS_SESSION.SET_CONTEXT( 'hr', 'dept', 'sales', 'APPSMGR', 12345 );
AppSvr
assigns a database connection to this session and initializes the session by issuing the following statement:
DBMS_SESSION.SET_IDENTIFIER( 12345 );
All SYS_CONTEXT
calls within this database session return application context values that belong only to the client session.
For example, SYS_CONTEXT('hr','id')
returns the value robert
.
When finished with the session, AppSvr
issues the following statement to clean up the client identity:
DBMS_SESSION.CLEAR_IDENTIFIER ( );
Even if another database user logged in to the database, this user cannot access the global context set by AppSvr
, because AppSvr
specified that only the application with user APPSMGR
logged in can see it. If AppSvr
used the following, then any user session with client ID set to 12345
can see the global context:
DBMS_SESSION.SET_CONTEXT( 'hr', 'id', 'robert', NULL , 12345 ); DBMS_SESSION.SET_CONTEXT( 'hr', 'dept', 'sales', NULL , 12345 );
Setting USERNAME
to NULL
enables different users to share the same context.
Note:
Be aware of the security implication of different settings of the global context.NULL
in the user name means that any user can access the global context. A NULL
client ID in the global context means that a session with an uninitialized client ID can access the global context. To ensure that only the user who has logged on can access the session, specify USER
instead of NULL
.You can query the client identifier set in the session as follows:
SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') FROM dual; SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') ------------------------------------------------- 12345
A security administrator can see which sessions have the client identifier set by querying the V$SESSION
view for the CLIENT_IDENTIFIER
and USERNAME
, for example:
COL client_identifier format a18 SELECT CLIENT_IDENTIFIER, USERNAME from V$SESSION; CLIENT_IDENTIFIER USERNAME ------------------ -------- 12345 APPSMGR
To check the amount of global context area (in bytes) being used, you can run the following query:
SELECT SYS_CONTEXT('USERENV','GLOBAL_CONTEXT_MEMORY') FROM dual; SYS_CONTEXT('USERENV','GLOBAL_CONTEXT_MEMORY') ---------------------------------------------- 584
See Also:
For more information about using theCLIENT_IDENTIFIER
predefined attribute of the USERENV
application context:
This section contains the following topics:
In a client session-based application context, you use Oracle Call Interface (OCI) functions to set and clear user session information, which is then stored in the User Global Area (UGA).
The advantage of this type of application context is that an individual application can check for specific user session data, rather than having the database perform this task. Another advantage is that the calls to set the application context value are included in the next call to the server, which improves performance.
However, be aware that application context security is compromised with a client session-based application context: any application user can set the client application context, and no check is performed in the database.
You configure the client session-based application context for the client application only. You do not configure any settings on the database server to which the client connects. Any application context settings in the database server do not affect the client session-based application context.
To configure a client session-based application context, use the OCIAppCtxSet
OCI function. A client session-based application context uses the CLIENTCONTEXT
namespace, updatable by any OCI client or by the existing DBMS_SESSION
package for application context. Oracle Database performs no privilege or package security checks for this type.
The CLIENTCONTEXT
namespace enables a single application transaction to both change the user context information and use the same user session handle to service the new user request. You can set or clear individual values for attributes in the CLIENTCONTEXT
namespace, or clear all their values.
An OCI client uses the OCIAppCtx
function to set variable length data for the namespace, called OCISessionHandle
. The OCI network single, round-trip transport sends all the information to the server in one round-trip. On the server side, you can query the application context information by using the SYS_CONTEXT
SQL function on the namespace. For example:
A JDBC client uses the oracle.jdbc.internal.OracleConnection
function to achieve the same purposes.
Any user can set, clear, or collect the information in the CLIENTCONTEXT
namespace, because it is not protected by package-based security.
See Also:
Oracle Call Interface Programmer's Guide for more information about client application contextsFor Oracle Call Interface, to set a value in the CLIENTCONTEXT
namespace, use a command in the following syntax:
err = OCIAppCtxSet((void *) session_handle,(dvoid *)"CLIENTCONTEXT",(ub4) 13, (dvoid *)attribute_name, length_of_attribute_name (dvoid *)attribute_value, length_of_attribute_value, errhp, OCI_DEFAULT);
In this specification:
session_handle
: Represents the OCISessionHandle
namespace.
attribute_name
: Name of attribute. For example, responsibility
, with a length of 14
.
attribute_value
: Value of attribute. For example, manager
, with a length of 7
.
For JDBC, use a command of the following form:
public void setApplicationContext( string CLIENTCONTEXT, string attribute, string value) throws SQLException;
In this specification:
attribute
: Represents the attribute whose value needs to be set.
value
: Represents the value to be assigned to the attribute.
See Also:
"Managing Scalable Platforms" in Oracle Call Interface Programmer's Guide for details about theOCIAppCtx
functionTo retrieve the client session ID, you can use the OCIStmtExecute
call with either of the following statements:
SELECT SYS_CONTEXT('CLIENTCONTEXT', attribute) FROM dual;
SELECT value FROM session_context WHERE namespace='CLIENTCONTEXT' AND 'attribute='CLIENT_IDENTIFIER' ;
The attribute
value can be any attribute value that has already been set in the CLIENTCONTEXT
namespace. Oracle Database only retrieves the set attribute; otherwise, it returns NULL
. Typically, you set the attribute by using the OCIAppCtxSet
call. In addition, you can embed a DBMS_SESSION.SET_CONTEXT
call in the OCI code to set the attribute value.
Example 7-10 shows how to use the OCIStmtExecute
call to retrieve a client session ID value.
Example 7-11 Retrieving a Client Session ID Value for Client Session-Based Contexts
1 oratext clientid[31];
2 OCIDefine *defnp1 = (OCIDefine *) 0;
3 OCIStmt *statementhndle;
4 oratext *selcid = (oratext *)"SELECT SYS_CONTEXT('CLIENTCONTEXT',
5 attribute) FROM DUAL";
6
7 OCIStmtPrepare(statementhndle, errhp, selcid, (ub4) strlen((char *) selcid),
8 (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
9
10 OCIDefineByPos(statementhndle, &defnp1, errhp, 1, (dvoid *)clientid, 31,
11 SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
12
13 OCIStmtExecute(servhndle, statementhndle, errhp, (ub4) 1, (ub4) 0,
14 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT);
15
16 printf("CLIENT_IDENTIFIER = %s \n", clientid);
In this example:
Lines 1–5: Create variables to store the client session ID, reference call for OCIDefine
, the statement handle, and the SELECT
statement to use.
Lines 7–8: Prepare the statement selcid
for execution.
Lines 10–11: Define the output variable clientid
for client session ID.
Lines 1 3–14: Execute the statement in the selcid
variable.
Line 16: Prints the formatted output for the retrieved client session ID.
For Oracle Call Interface, to clear a setting in CLIENTCONTEXT
, set the value to NULL
or to an empty string by using one of the following commands:
(void) OCIAppCtxSet((void *) session_handle, (dvoid *)"CLIENTCONTEXT", 13, (dvoid *)attribute_name, length_of_attribute_name, (dvoid *)0, 0,errhp OCI_DEFAULT);
or
(void) OCIAppCtxSet((void *) session_handle, (dvoid *)"CLIENTCONTEXT", 13 (dvoid *)attribute_name, length_of_attribute_name, (dvoid *)"", 0,errhp, OCI_DEFAULT);
For JDBC, use the following command:
public void setApplicationContext(String CLIENTCONTEXT, string attribute, string value) throws SQLException;
In this specification:
attribute
: Represents the attribute whose value needs to be cleared.
value
: Either 0
or the null string ("")
.
For Oracle Call Interface (OCI), use a command of the following form:
err = OCIAppCtxClearAll((void *) session_handle,
(dvoid *)"CLIENTCONTEXT", 13,
errhp, OCI_DEFAULT);
For JDBC, use a command of the following form:
public void clearAllApplicationContext( String CLIENTCONTEXT) throws SQLException;
Table 7-3 lists data dictionary views that you can query to find information about application contexts. For detailed information about these views, see Oracle Database Reference.
Table 7-3 Application Context Views
Tip:
In addition to these views, check the database trace file if you find errors when running applications that use application contexts. See Oracle Database Performance Tuning Guide for more information about trace files. TheUSER_DUMP_DEST
initialization parameter specifies the current location of the trace files. You can find the value of this parameter by issuing SHOW PARAMETER USER_DUMP_DEST
in SQL*Plus.