About Application Session APIs
All application session APIs are exposed through class ApplicationSessionService as static methods. The APIs operate on the current application session, which is set up based on the current Subject. Inside each API, an identity assertion is performed internally, to make sure the current application session matches the subject. If a mismatch is found, an ApplicationSesseionException exception is thrown. The caller code of the application session API should always be executed inside Subject.doAs, to be invoked as the subject. See the JDK’s Subject.doAs for more information.
This section describes the following topics:
About Application Session APIs
This section describes the following topics:
About Attaching to an Application Session
Attach the current user’s application session to the given database connection.
For application code to attach to the current user’s application session, no code based permission is needed. The application session works as is, no extra privilege is elevated through the attach.
Syntax
public static void attachSession(java.sql.Connection conn)
throws ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
Example
See Example: Application Session APIs: AttachSession and DetachSession and Example: Namespace APIs.
Detaching from an Application Session
Detach the current user’s application session from the given database connection.
It is always a good practice to detach the application session at the application code’s final block. Not doing so may give an attached connection to some code that is not running under the correct user. It is caller’s responsibility to properly detach the application session once used.
If detach is not called, but attach is called again on the same connection, the server forces the detach from the previous attached application session, and attaches to the current application session.
Syntax
public static void detachSession(java.sql.Connection conn)
throws ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
Example
Example: Application Session APIs: AttachSession and DetachSession shows sample code that uses the attach and detach API with a database query. The caller must decide the boundary of the attach and detach calls, based on the needs of the query.
Example: Application Session APIs: AttachSession and DetachSession
/**
* Typical application code calling attach/detach for database query
*/
public void queryHR(Connection conn) {
String query = " select emp.employee_id, emp.salary from hr.employees emp";
Statement stmt = null;
ResultSet rs = null;
String id, salary;
try {
// attach connection to the current application session
ApplicationSessionService.attachSession(conn);
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()) {
id = rs.getString("employee_id");
salary = rs.getString("salary");
}
} catch (ApplicationSessionException e) {
} catch (SQLException e) {
} finally {
// detach the current application session from the connection
try { ApplicationSessionService.detachSession(conn); } catch (Exception e) {}
if (stmt != null) try {stmt.close();} catch (SQLException e) {};
if (rs != null) try { rs.close();} catch (SQLException e{};
}
}
Destroying an Application Session
Destroys the current application session at the database, and removes it from current thread’s execution context. This should be invoked by the application at logout. It destroys the current application session originally set up by the filter.
Syntax
public static void destroySession(java.sql.Connection conn)
throws ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
Example
Example: Application Session APIs: DestroySession shows sample code that destroys the application session service.
Example: Application Session APIs: DestroySession
void doLogout(HttpServletRequest request) {
DataSource dataSource = null;
Connection conn = null;
try {
InitialContext ic;
try {
ic = new InitialContext();
dataSource = (DataSource)ic.lookup("jdbc/myDBDS");
if (dataSource != null)
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
// invalidate Http session
request.getSession().invalidate();
// destroy XS session at DB
ApplicationSessionService.destroySession(conn);
} catch (ApplicationSessionException e) {
e.printStackTrace();
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
About the Privilege Elevation API
This section describes the following topic: Enabling a Dynamic Role in the Application Session.
Enabling a Dynamic Role in the Application Session
Attaches the current application session to a given database connection, and enables the Real Application Security dynamic role in the attached application session. This allows trusted application code to have higher privileges temporarily in order to perform some database operations, such as setting up application namespace.
This is for certain trusted application code to elevate the application session privilege. A Real Application Security dynamic role is enabled during attach. The trusted code is identified by java code permission.
Syntax
public static void attachSessionPrivileged(java.sql.Connection conn,
java.lang.String role)
throws ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
role |
The given dynamic role; must be request scope |
Example
Each given dynamic role is associated with a code base permission as shown in Example: Privilege Elevation API (permission grant in jazn-data.xml)
Usage Notes
The permission is always checked internally in the API, whether the java security manager is on or off. If the caller has the permission (that implies that the given role also matches the role defined in the policy file), the given dynamic role is enabled during attach; otherwise, the API fails with an AccessControlException.
The caller code (caller.jar file) and application session service code (xsee.jar) should both have the SessioncodePermission permission. This is sufficient when the caller.jar is invoked directly by the container. When caller.jar is invoked by another application code, it is up to the caller to decide whether the application code needs to have this permission. If the caller does not need the application to have this permission, the caller can invoke attachSessionPrivileged under AccessController.doPrivileged with a null AccessControllerContext. See the Java API for details. By doing this, the caller.jar fully trusts the application code.
Note that the dynamic role is only enabled on the attached application session, not the current application session. It is enabled within the window of attach and detach. The dynamic role must be defined as request scope at the database; otherwise, the following exception ORA-46055: invalid role specified is thrown.
Example: Privilege Elevation API
<grant>
<grantee>
<codesource>
<url>file:${domain.home}/servers/DefaultServer/tmp/_WL_user/MyWar/pi47ig/war/WEB-INF/lib/trusted.jar' </url>
</codesource>
</grantee>
<permissions>
<permission>
<class>oracle.security.xs.ee.session.SessionCodePermission</class>
<name> MY_NS_DROLE</name>
<actions>attach </actions>
</permission>
</permissions>
</grant>
<grant>
<grantee>
<codesource>
<url>file:${domain.home}/lib/xsee.jar</url>
</codesource>
</grantee>
<permissions>
<permission>
<class>oracle.security.xs.ee.session.SessionCodePermission</class>
<name>MY_NS_DROLE</name>
<actions>attac </actions>
</permission>
</permissions>
</grant>
About Namespace APIs
This section describes the following topics:
About Creating a Namespace
Creates a namespace in the current application session. The namespace given must be predefined at the database, and the namespace ACL must allow the attached application session to perform a MODIFY_NAMESPACE operation, unless the ADMIN_ANY_NAMESPACE privilege is enabled in the application session.
Syntax
public static void createNamespace(java.sql.Connection conn,
java.lang.String name)
throws ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
name |
The given namespace name |
Example
About Deleting a Namespace
Deletes a namespace from the current application session. The namespace given must be predefined at the database, and the namespace ACL must allow the attached application session to perform a MODIFY_NAMESPACE operation, unless the ADMIN_ANY_NAMESPACE privilege is enabled in the application session.
Syntax
public static void deleteNamespace(java.sql.Connection conn,
java.lang.String name)
throws NamespaceNotFoundException,
ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
name |
The given namespace name. |
Example
About Setting the Namespace Attribute
Sets the attribute value to the namespace in the current application session. The namespace given must be predefined at the database, and the namespace ACL must allow the attached application session to perform a MODIFY_ATTRIBUTE operation, unless the ADMIN_ANY_NAMESPACE privilege is enabled in the application session.
If the attribute does not exist on the namespace, the API creates the attribute with the given value; otherwise, it simply sets the existing value to the given value.
Syntax
public static void setNamespaceAttribute(java.sql.Connection conn,
java.lang.String name,
java.lang.String attribute,
java.lang.String value)
throws NamespaceNotFoundException,
ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
name |
The given namespace name |
attribute |
The given namespace attribute name |
value |
The given namespace attribute value |
Example
About Deleting a Namespace Attribute
Deletes the attribute from the namespace in the current application session. The namespace given must be predefined at the database, and the namespace ACL must allow the attached application session to perform a MODIFY_ATTRIBUTE operation, unless the ADMIN_ANY_NAMESPACE privilege is enabled in the application session.
Syntax
public static void deleteNamespaceAttribute(java.sql.Connection conn,
java.lang.String name,
java.lang.String attribute)
throws NamespaceNotFoundException,
ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
name |
The given namespace name |
attribute |
The given namespace attribute name |
Example
Getting a Namespace Attribute
Gets the attribute from the namespace in the current application session. The given namespace must be created. No database connection is needed and no privilege is checked for this operation.
The APIs that change namespace (other than getNamespaceAttribute) have a database connection as an input parameter. Those APIs update the namespace in the current application session in the JVM, as well as serialize the change to the database table. The connection must be attached. It uses the attached application session to determine whether the server can authorize the namespace change.
To allow only certain trusted application code to set up namespace. The connection can be attached with a dynamic role, which has elevated privileges (MODIFY_NAMESPACE, MODIFY_ATTRIBUTE) on the namespace. This is achieved using the attachSessionPrivileged API, and only granting the namespace privileges to the dynamic role.
Syntax
public static java.lang.String getNamespaceAttribute(java.lang.String name,
java.lang.String attribute)
throws NamespaceNotFoundException,
ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
name |
The given namespace name |
attribute |
The given namespace attribute name |
Example
Example: Namespace APIs shows a sample servlet filter that sets up namespace using namespace APIs and uses the application session privilege elevation API.
Important Points to Know About Using Application Namespace
The following usage information summarizes important points about using application namespace.
-
The Real Application Security filter caches all the application namespace to the current application session.
-
For first time access, a new application session must be created in the database. No application namespace has been set up yet at this time.
-
For the user’s subsequent access, the filter always brings all the namespaces created for the application session, and caches them in the current application session in JVM.
-
-
Application code always accesses namespace from the current application session. Each update operation is a round trip to the server to change the values in the table and current application session (JVM). That is why each update API has a database connection parameter. However, the read attribute is a local operation to read from the current application session in JVM without accessing the database.
-
Whenever a namespace change is successfully done, the change is propagated to the already attached application sessions, as well as newly attached application sessions because all these attached application sessions refer to the single source - the current application session.
-
The namespace in the current application session is consistent within an http request scope for the web application. Even the namespace can be changed at any time by other applications. The change is only picked up once at the beginning of the current http request by the Real Application Security filter. All attaches that happen within the same http request refer to the same namespace in the current application session.
-
Application code has complete control for changing the namespace value. It can read the current application session’s namespace at any time and decide whether to update the namespace by calling the namespace APIs.
Example: Namespace APIs
/**
* Trusted application code (servlet filter) sets up namespace
* Using privilege elevation and namespace APIs
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Connection conn = null;
try {
conn = myDatasource.getConnection();
// Attach an application session with a dynamic role.
ApplicationSessionService.attachSessionPrivileged(conn, "myNSRole");
try {
// Get the current value.
String currentValue = ApplicationSessionService.getNamespaceAttribute("mySecuredNS", "myAttribute");
// If the current value is not desired, set it.
if ("myValue".compareToIgnoreCase(currentValue) != 0)
ApplicationSessionService.setNamespaceAttribute(conn, "mySecuredNS", "myAttribute", "myValue");
} catch (NamespaceNotFoundException e) {
// Namespace is not found, create it.
ApplicationSessionService.createNamespace(conn, "mySecuredNS");
// Set the attribute.
ApplicationSessionService.setNamespaceAttribute(conn, "mySecuredNS", "myAttribute", "myValue");
}
} catch (SQLException e) {
} catch (ApplicationSessionException e) {
} finally {
// Detach an application session.
try { ApplicationSessionService.detachSession(conn); } catch (Exception e) {}
if (conn != null) try { conn.close();} catch (Exception e) {}
}
// Execution of application code.
chain.doFilter(request, response);
About the Check Privilege API
This section describes the following topic: Checking a Privilege on the ACLs.
Checking a Privilege on the ACLs
Checks the privilege on the ACLs using the attached application session of the given connection and includes these usage notes:
-
An attached connection must be given. The privilege check is based on the attached application session. Note that an attached application session can have extra privileges compared to the current application session through the
attachSessionPrivilegedcall. -
The API takes the input parameter of ACL IDs, which can be queried from the table using the
ORA_GET_ACLIDoperator. The operator returns a set of ACL IDs associated with the current row. -
This API takes the input parameter of privilege name. This input parameter can be DML privileges, such as
SELECTorUPDATE, or it can be any user defined privilege.
Syntax
public static boolean checkPrivilege(java.sql.Connection conn,
byte[] acls,
java.lang.String privilege)
throws ApplicationSessionException
Parameter
| Parameter | Description |
|---|---|
conn |
The JDBC connection for database server roundtrip |
acls |
The given ACL IDs in row format |
privilege |
The given privilege name |
Example
Example: CheckPrivilege API shows getting the ACL associated with the row and checking the UPDATE privilege on the ACL.
Example: CheckPrivilege API
public Collection<Employee> queryHR(Connection conn ) {
Statement stmt = null;
ResultSet rs = null;
Collection<Employee> result = new ArrayList<Employee>();
try {
// attach session
ApplicationSessionService.attachSession(conn);
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()) {
Employee emp = new Employee();
emp.setId(rs.getString("EMPLOYEE_ID"));
AuthorizationIndicator ai =
((OracleResultSet)rs).getAuthorizationIndicator("salary");
if (ai == AuthorizationIndicator.NONE) {
emp.setSalary(rs.getString("salary"));
} else {
emp.setSalary("******") ;
}
// get ACL associated with the row
emp.setAcl(rs.getBytes("acl_id"));
// check "update" privilege
boolean canUpdate = ApplicationSessionService.checkPrivilege(conn, emp.getAcl(), "UPDATE");
emp.setUpdate(canUpdate);
result.add(emp);
emp.setFname(rs.getString("first_name"));
emp.setLname(rs.getString("last_name"));
emp.setEmail(rs.getString("email"));
emp.setPhone(rs.getString("phone_number"));
emp.setManagerId(rs.getString("manager_id"));
emp.setDepId(rs.getString("department_id"));
}
} catch (ApplicationSessionException e) {
e.printStackTrace();
// process me
} catch (SQLException e) {
// process me
e.printStackTrace();
} finally {
if (stmt != null) try {stmt.close();} catch (SQLException e) {};
if (rs != null) try { rs.close();} catch (SQLException e) {};
try {ApplicationSessionService.detachSession(conn);} catch (ApplicationSessionException e) {};
}
return result;
}