Human Resources Demo Use Case: Implementation in Java
This section describes how an application session service supports user and roles managed externally by Oracle Fusion Middleware. This Java example is based on the Security Human Resources (HR) scenario. It uses the EMPLOYEES table in the sample HR schema.
See Also: For information about user and group to application roles mapping, see About the HR Demo Use Case - User Roles.
This example includes the following files and employee records that the three types of users can access:
-
Setting Up the HR Demo Application for External Principals (setup.sql)
-
About the Application Session Filter Configuration File (web.xml)
-
About the Filter to Set Up the Application Namespace (MyFilter.java)
Setting Up the HR Demo Application for External Principals (setup.sql)
Example: Set Up the HR Demo Application for External Principals shows a set up script (setup.sql) for setting up the HR Demo application for external principals.
This setup script performs the following operations:
-
Creates a dynamic role,
HROBJ, for object privileges for the external user -
Creates a security class,
HRPRIVS, with privilegeview_sensitive_info, and aggregate privilegeupdate_infothat implies data privileges, update, delete, insert, which come from pre-defined security classDML. -
Creates an
EMPACL,EMP_ACL, to grantEMP,HRMGRandHRREPprivileges to access employee record in the restricted departments. Note that each external principal, (application role:HRREP,HRMGR, andEMP) must match the OPSS policy store GUID values. -
Creates an self ACL,
SELF_ACL, to grantEMPprivileges for an employee to see and update their own record. -
Creates a Manager ACL,
MGR_ACL, to allow a manager to see their employee’s salary information. -
Creates a data security policy,
EMPLOYEE_DS, for theEMPLOYEEStable. The policy defines an instance set to control access to the employees in department 60 and 100 toEMP_ACL. It also defines an attribute constraint to control access to the sensitive SALARY column. -
Defines two additional instance sets to
SELF_ACLandMGR_ACLthat are appended to the data security policy,EMPLOYEE_DS. -
Grants to the dispatcher some additional privileges.
Example: Set Up the HR Demo Application for External Principals
Rem Copyright (c) 2009, 2014, Oracle and/or its affiliates.
Rem All rights reserved.
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
-- A PL/SQL function to determine manager-report relationship
conn hr/hr;
create or replace package hrutil as
function ismyreport(id IN PLS_INTEGER)
return PLS_INTEGER ;
end hrutil;
/
create or replace package body hrutil as
function ismyreport(id IN PLS_INTEGER)
return PLS_INTEGER is
mycount PLS_INTEGER ;
myid PLS_INTEGER ;
begin
select employee_id into myid from hr.employees
where UPPER(email) = XS_SYS_CONTEXT('PROFILE_NS','EMAIL');
select count(employee_id) into mycount from hr.employees
where employee_id = id start with manager_id = myid
connect by prior employee_id = manager_id ;
return mycount ;
end ismyreport ;
end hrutil ;
/
-- Create a dynamic role for object privileges for external users.
connect sys/password as sysdba
show con_name;
-- Create a dynamic role for HR object privileges.
exec xs_principal.delete_principal('HROBJ',XS_ADMIN_UTIL.CASCADE_OPTION);
exec xs_principal.create_dynamic_role('HROBJ');
-- Create a db role to have HR object privileges.
drop role hr_db_obj;
create role hr_db_obj;
-- Grant object privilege to the db role.
grant select, insert, update, delete on hr.employees to hr_db_obj;
-- Grant db role to dynamic role.
grant hr_db_obj to HROBJ;
-- Create a security class with privilege view_sensitive_info, and
-- aggregate privilege update_info that implies data privileges,
-- update, delete, insert, which come from pre-defined security class
-- DML.
DECLARE
priv_list XS$PRIVILEGE_LIST;
BEGIN
priv_list :=XS$PRIVILEGE_LIST(
XS$PRIVILEGE(name=>'VIEW_SENSITIVE_INFO'),
XS$PRIVILEGE(name=>'UPDATE_INFO',
implied_priv_list=>XS$NAME_LIST
('"UPDATE"', '"DELETE"', '"INSERT"')));
xs_security_class.create_security_class(
name=>'HRPRIVS',
parent_list=>XS$NAME_LIST('DML'),
priv_list=>priv_list);
END;
/
-- External Principal (app role) Used for data security:
-- Such a principal must match the OPSS policy store.
-- roleName="HRREP" guid="37ED0D108C2F11E2BF802D569259982"
-- roleName="HRMGR" guid="4077A2B08C2F11E2BF802D569259982"
-- roleName="EMP" guid="F917C3608CF011E2BF802D569259982"
-- Create an EMP Acl to grant EMP, HRMGR and HRREP privileges to access an employee record in the restricted departments.
DECLARE
ace_list XS$ACE_LIST;
BEGIN
ace_list := XS$ACE_LIST(
XS$ACE_TYPE(privilege_list=>XS$NAME_LIST('"SELECT"','VIEW_SENSITIVE_INFO'),
granted=>true,
principal_name=>'"37ED0D108C2F11E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL),
XS$ACE_TYPE(privilege_list=>XS$NAME_LIST('UPDATE_INFO'),
granted=>true,
principal_name=>'"4077A2B08C2F11E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL),
XS$ACE_TYPE(privilege_list=>XS$NAME_LIST('"SELECT"'),
granted=>true,
principal_name=>'"F917C3608CF011E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL));
xs_acl.create_acl(name=> 'EMP_ACL',
ace_list=> ace_list,
sec_class=>'HRPRIVS',
description=> 'Employee access to his/her data');
END;
/
-- Create a self Acl to grant EMP privileges to for an employee to see and update their own record.
-- Grant UPDATE, VIEW_SENSITIVE_INFO privileges to the EMP role.
DECLARE
ace_list XS$ACE_LIST;
BEGIN
ace_list := XS$ACE_LIST(
XS$ACE_TYPE(privilege_list=> XS$NAME_LIST('"UPDATE"', 'VIEW_SENSITIVE_INFO'),
principal_name=>'"F917C3608CF011E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL));
xs_acl.create_acl(name=> 'SELF_ACL',
ace_list=> ace_list,
sec_class=>'HRPRIVS',
description=> 'Employee access to his/her data');
END;
/
-- Create Manager ACL, to allow a manager to see their employee's salary.
-- Grant VIEW_SENSITIVE_INFO privileges to EMP role on the Manager's employees.
--
DECLARE
ace_list XS$ACE_LIST;
BEGIN
ace_list := XS$ACE_LIST(
XS$ACE_TYPE(privilege_list=> XS$NAME_LIST('VIEW_SENSITIVE_INFO'),
principal_name=>'"F917C3608CF011E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL));
xs_acl.create_acl(name=> 'MGR_ACL',
ace_list=> ace_list,
sec_class=>'HRPRIVS',
description=> 'Manager can see his reports salaray');
END;
/
-- Create data security policy for the EMPLOYEE table. The policy defines
-- an instant set to control the access to the employees in department
-- 60 and 100. It also defines an attribute constraint to control
-- the access to sensitive column SALARY.
DECLARE
inst_sets XS$REALM_CONSTRAINT_LIST;
attr_secs XS$COLUMN_CONSTRAINT_LIST;
BEGIN
inst_sets :=
XS$REALM_CONSTRAINT_LIST(
XS$REALM_CONSTRAINT_TYPE(realm=> 'DEPARTMENT_ID in (60, 100)',
acl_list=> XS$NAME_LIST('EMP_ACL')));
attr_secs :=
XS$COLUMN_CONSTRAINT_LIST(
XS$COLUMN_CONSTRAINT_TYPE(column_list=> XS$LIST('SALARY'),
privilege=> 'VIEW_SENSITIVE_INFO'));
xs_data_security.create_policy(
name=>'EMPLOYEES_DS',
realm_constraint_list=>inst_sets,
column_constraint_list=>attr_secs);
END;
/
-- Add more instance sets to the above data security.
declare
inst1 xs$REALM_CONSTRAINT_TYPE;
inst2 xs$REALM_CONSTRAINT_TYPE;
begin
inst1 := xs$REALM_CONSTRAINT_TYPE(realm=> 'UPPER(email) = XS_SYS_CONTEXT(''PROFILE_NS'',''EMAIL'')',
acl_list=> XS$NAME_LIST('SELF_ACL'));
xs_data_security.append_realm_constraints('EMPLOYEES_DS', inst1);
inst2 := xs$REALM_CONSTRAINT_TYPE(realm=> 'hr.hrutil.ismyreport(employee_id) = 1',
acl_list=> XS$NAME_LIST('MGR_ACL'));
xs_data_security.append_realm_constraints('EMPLOYEES_DS', inst2);
end;
/
-- Apply the data security policy on the table.
begin
XS_DATA_SECURITY.apply_object_policy(schema=>'HR', object=>'EMPLOYEES',
policy=>'EMPLOYEES_DS');
end;
/
-- Grant more privileges for the dispatcher.
exec XS_ADMIN_UTIL.GRANT_SYSTEM_PRIVILEGE('ADMIN_ANY_NAMESPACE','ts',XS_ADMIN_UTIL.PTYPE_XS);
grant select on sys.dba_xs_session_roles to ts_role;
EXIT;
About the Application Session Filter Configuration File (web.xml)
Example: A Complete Application Session Filter Sample Configuration shows a complete application session filter sample configuration file (web.xml) that includes the filter, its parameters, and the listener. It references a filter for setting up the namespace (MyFilter.java) shown in Example: Filter to Set Up Application Namespace, and the sample servlet applications named MyHR.java shown in Example: Sample Servlet Application MyHR.java, in addition to: MySession.java, MyUpdate.java, and LogoutServlet.java, which are not shown.
MySession queries the V$XS_SESSION_ROLES view to show the roles in the application session, queries the users in XS$SESSION namespace to show the user in the application session, and queries the V$XS_SESSION_NS_ATTRIBUTES view to show the namespace in the application session, and then attaches to an application session.
MyUpdate performs an update on the HR.EMPLOYEES table to update the phone number for an employee.
LogoutServlet performs a logout operation, and then destroys the application session at the database.
In the ApplicationSessionFilter filter configuration, the filter section references the class ApllicationSessionFilter, describes a parameter application.datasource with a parameter value jdbc/myDBDS, and describes a parameter dynamic roles with a value of HROBJ that was created in the set up script in Example: Set Up the HR Demo Application for External Principals.
Example: A Complete Application Session Filter Sample Configuration
<?xml version = '1.0' encoding = 'UTF-8'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<filter>
<filter-name>JpsFilter</filter-name>
<filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
<init-param>
<param-name>enable.anonymous</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>remove.anonymous.role</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>application.name</param-name>
<param-value>MyHRApp</param-value>
</init-param>
<!-- Following needed for Menu Security -->
<!--init-param>
<param-name>oracle.security.jps.jaas.mode</param-name>
<param-value>subjectOnly</param-value>
</init-param-->
</filter>
<filter>
<filter-name>ApplicationSessionFilter</filter-name>
<filter-class>oracle.security.xs.ee.session.ApplicationSessionFilter</filter-class>
<init-param>
<param-name>application.datasource</param-name>
<param-value>jdbc/myDBDS</param-value>
</init-param>
<init-param>
<param-name>dynamic.roles</param-name>
<param-value>HROBJ</param-value>
</init-param>
<!--
<init-param>
<param-name>dispatcher.pool.max</param-name>
<param-value>90</param-value>
</init-param>
-->
<!-- init-param>
<param-name>application.id</param-name>
<param-value>MyHRApp</param-value>
</init-param>
<init-param>
<param-name>session.provider</param-name>
<param-value>XS</param-value>
</init-param>
<init-param>
<param-name>db.url</param-name>
<param-value>jdbc:oracle:thin:@myhost:1521:orcl</param-value>
</init-param>
<init-param>
<param-name>dispatcher.id</param-name>
<param-value>ts</param-value>
</init-param>
<init-param>
<param-name>dispatcher.pwd.map</param-name>
<param-value>XS_MAP</param-value>
</init-param>
<init-param>
<param-name>dispatcher.pwd.key</param-name>
<param-value>XS_KEY</param-value>
</init-param>
<init-param>
<param-name>dispatcher.pool.min</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>dispatcher.pool.max</param-name>
<param-value>10</param-value>
</init-param -->
<!--init-param>
<param-name>namespaces</param-name>
<param-value>sec_ns</param-value>
</init-param-->
</filter>
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>trusted.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JpsFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>ApplicationSessionFilter</filter-name>
<url-pattern>/myhr</url-pattern>
<url-pattern>/mysession</url-pattern>
<url-pattern>/myupdate</url-pattern>
<url-pattern>/logout</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/myhr</url-pattern>
<url-pattern>/mysession</url-pattern>
<url-pattern>/myupdate</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<listener>
<listener-class>oracle.security.xs.ee.session.ApplicationSessionListener</listener-class>
</listener>
<servlet>
<servlet-name>MySession</servlet-name>
<servlet-class>app.MySession</servlet-class>
</servlet>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>app.MyLogout</servlet-class>
</servlet>
<servlet>
<servlet-name>MyHR</servlet-name>
<servlet-class>app.MyHR</servlet-class>
</servlet>
<servlet>
<servlet-name>MyUpdate</servlet-name>
<servlet-class>app.MyUpdate</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MySession</servlet-name>
<url-pattern>/mysession</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MyHR</servlet-name>
<url-pattern>/myhr</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MyUpdate</servlet-name>
<url-pattern>/myupdate</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>my servlet</web-resource-name>
<url-pattern>/myhr</url-pattern>
<url-pattern>/mysession</url-pattern>
<url-pattern>/myupdate</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>valid-users</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT,FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>valid-users</role-name>
</security-role>
</web-app>
About the Sample Servlet Application (MyHR.java)
Example: Sample Servlet Application MyHR.java shows the sample servlet application named MyHR.java, which is referenced in the application session filter sample configuration (web.xml file) shown in Example: A Complete Application Session Filter Sample Configuration.
The MyHR application performs a query on the EMPLOYEES table and returns the results. If you have authorization, depending on your login credentials, you can perform certain tasks as described in:
-
About the HR Demo (1) - Logged in as Employee LPOPP
As an employee, you can see your own salary information, but no one elses, and you can update only your own contact information.
-
About the HR Demo (2) - Logged in as HRMGR
If you are logged in as a HR Manager, you can see the salary records of all employees and you can update their contact information.
-
About the HR Demo (3) - Logged in as a Team Manager
If you are logged in as a Team Manager, you can see only your teams’s employees salary information, but you cannot update their contact information, only your own contact information.
From a check of the privilege on the ACLs (checkPrivilege), if you have UPDATE privilege, then you are authorized to perform an update of that employee’s record and the EMPLOYEE_ID will show a link that allows you access to that employee’s record.
Example: Sample Servlet Application MyHR.java
/* Copyright (c) 2009, 2014, Oracle and/or its affiliates.
All rights reserved.*/
package app;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import oracle.jdbc.OracleResultSet;
import oracle.jdbc.OracleResultSet.AuthorizationIndicator;
import oracle.security.xs.ee.session.ApplicationSessionException;
import oracle.security.xs.ee.session.ApplicationSessionService;
public class MyHR extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
String query = " select emp.EMPLOYEE_ID, emp.first_name, emp.last_name, " +
" emp.email, emp.phone_number, salary, emp.manager_id, " +
" emp.department_id,ora_get_aclids(emp) as acl_id" +
" from hr.employees emp";
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public void queryHR(PrintWriter out) throws ApplicationSessionException {
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();
}
try {
queryHR(conn, out);
} catch (Exception e) {
e.printStackTrace();
}
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter pw = response.getWriter();
pw.println(HEADER);
pw.println("<h1><font size=\"+2\">RAS Session Service Demo</font></h1>");
pw.println("<font size=\"+1\">");
pw.println("You are logged in as <b>" + request.getRemoteUser() + "</b>");
try {
queryHR(pw);
} catch (ApplicationSessionException e) {
e.printStackTrace();
}
pw.println(FOOTER);
pw.close();
}
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;
}
public void queryHR(Connection conn, PrintWriter out ) {
Collection<Employee> list = queryHR(conn);
PrintWriter pw = out;
pw.println("<br>Displaying employee record(s) that you can access.<br>");
pw.println("</font>");
pw.println("<i>NOTE: Salary is only shown if you are authorized to view,
and ID is shown as a link if you are authorized to perform an update.</i><br>");
out.println("<table border=\"1\">");
String tmp;
if (list.size() > 0) {
out.println("<tr>");
out.println("<th>ID</th>");
out.println("<th>First Name</th>");
out.println("<th>Last Name</th>");
out.println("<th>Email</th>");
out.println("<th>Phone</th>");
out.println("<th>Salary</th>");
out.println("<th>Department ID</th>");
out.println("<th>Manager ID</th>");
out.println("</tr>");
}
for (Employee e: list) {
if (e.canUpdate()) {
tmp = "<a href=\"update.jsp?id=" + e.getId() + "\">" + e.getId() + "</a>";
} else {
tmp = e.getId();
}
out.println("<tr><td>" + tmp + "</td>");
out.println("<td>" + e.getFname() + "</td>");
out.println("<td>" + e.getLname() + "</td>");
out.println("<td>" + e.getEmail() + "</td>");
out.println("<td>" + e.getPhone() + "</td>");
out.println("<td>" + e.getSalary() + "</td>");
out.println("<td>" + e.getDepId() + "</td>");
out.println("<td>" + e.getManagerId() + "</td></tr>");
}
out.println("</TABLE>");
};
class Employee {
String id;
String salary;
boolean update;
String fname;
String lname;
String email;
String phone;
String managerId;
String depId;
byte[] acl;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getSalary() {
return salary;
}
public void setUpdate(boolean canUpdate) {
this.update = canUpdate;
}
public boolean canUpdate() {
return update;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getFname() {
return fname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getLname() {
return lname;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPhone() {
return phone;
}
public void setManagerId(String managerId) {
this.managerId = managerId;
}
public String getManagerId() {
return managerId;
}
public void setDepId(String depId) {
this.depId = depId;
}
public String getDepId() {
return depId;
}
public void setAcl(byte[] acl) {
this.acl = acl;
}
public byte[] getAcl() {
return acl;
}
}
private static String HEADER = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>"
+ "<meta content=\"text/html; charset=UTF-8\" http-equiv=\"content-type\"/>"
+ "<title>Oracle</title>"
+ "<link href=\"css/general.css\" type=\"text/css\" rel=\"stylesheet\"/>"
+ "<link href=\"css/window.css\" type=\"text/css\" rel=\"stylesheet\"/>"
+ "<link href=\"css/login.css\" type=\"text/css\" rel=\"stylesheet\"/>"
+ "<script type=\"text/javascript\">"
+ " if (top != self) top.location.href = location.href;"
+ "</script>"
+ "<style type=\"text/css\">"
+ "html { background-color: #001C34;}"
+ "</style>"
+ "</head>"
+ "<body onload=\"document.loginData.j_username.focus();\">"
+ " <div id=\"top\">"
+ " <div id=\"login-header\">"
+ " <div id=\"login-logo\">"
+ " <img src=\"images/logo.png\"/>"
+ "</div>"
+ " </div>"
+ " <div id=\"content\">"
+ "<div id=\"app_data\"><div id=\"title\"></div>";
private static String FOOTER = "<a href=\"/myapp/logout\">Logout</a>"
+ "</div></div><div id=\"info\"></div></div></body></html>";
}
About the Filter to Set Up the Application Namespace (MyFilter.java)
Example: Filter to Set Up Application Namespace shows a filter to set up the application namespace. This filter is named MyFilter.java, which is referenced in the application session filter sample configuration (web.xml file) shown in Example: A Complete Application Session Filter Sample Configuration.
This filter should be deployed as a separate jar, and SessionCodePermission should be granted to the jar file.
This filter first queries the V$XS_SESSION_ROLES view to show the roles in the Real Security Application session. Next, this filter demonstrates how trusted application code (a filter) firsts checks to see if a namespace exists (getNamespaceAttribute); then if not, it can set up a security critical namespace using session privilege elevation (attachSessionPrivileged) and namespace APIs (createNamespace, and setNamespaceAttribute) to create the namespace and set some namespace attributes.
Example: Filter to Set Up Application Namespace
/* Copyright (c) 2009, 2014, Oracle and/or its affiliates.
All rights reserved.*/
package trusted;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import oracle.security.xs.ee.session.ApplicationSessionException;
import oracle.security.xs.ee.session.ApplicationSessionService;
import oracle.security.xs.ee.session.NamespaceNotFoundException;
/**
* Demonstrate how trusted application code (a filter) can set up
* security critical namespace using session privilege elevation and
* namespace APIs.
*
* The filter should be deployed as a separate jar, and SessionCodePermission
* should be granted to the jar.
*/
public class MyFilter implements Filter {
private FilterConfig _filterConfig = null;
DataSource myDatasource = null;
public void init(FilterConfig filterConfig) throws ServletException {
_filterConfig = filterConfig;
}
public void destroy() {
_filterConfig = null;
}
public void querySessionRoles(Connection conn) throws SQLException {
String query =
"select role_name from v$xs_session_roles order by role_name";
String roles = null;
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
System.out.println("<p> roles in RAS session (from myfilter):</p>");
System.out.println("<TABLE>");
while (rs.next()) {
roles = rs.getString(1);
System.out.println("<tr><td>" + roles + "</td></tr>");
}
System.out.println("</TABLE>");
} finally {
}
return;
}
private boolean namespaceExists(String ns, String attribute, String value) throws ApplicationSessionException {
try {
return value.equalsIgnoreCase(ApplicationSessionService.getNamespaceAttribute(ns, attribute));
} catch (NamespaceNotFoundException e) {
return false;
}
}
private Connection getConnection() {
DataSource dataSource = null;
InitialContext ic;
try {
ic = new InitialContext(); //TODO cache context
dataSource = (DataSource)ic.lookup("jdbc/myDBDS");
if (dataSource != null)
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
} catch (NamingException e) {
e.printStackTrace();
}
return null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
Connection conn = null;
try {
String email = ((HttpServletRequest)request).getRemoteUser();
if ( email != null && !namespaceExists("PROFILE_NS", "EMAIL", email )) {
conn = getConnection();
//AccessController.doPrivileged(new AttachAction(conn), null);
ApplicationSessionService.attachSessionPrivileged(conn, "SESSION_NS_DROLE");
ApplicationSessionService.createNamespace(conn, "PROFILE_NS");
ApplicationSessionService.setNamespaceAttribute(conn, "PROFILE_NS", "EMAIL", email);
ApplicationSessionService.detachSession(conn);
}
} catch (ApplicationSessionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
try {
chain.doFilter(request, response);
} catch (IOException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
}
}
}
About the HR Demo Use Case - User Roles
In the HR Demo Use Case, the Identity Management store contains the user name, user name’s password, and group name, while the OPSS security store contains the application roles and the user and group to application roles mapping. Example: User and Group to Application Roles Mapping shows a code snippet for the user and group to application roles mapping for one user LPOPP.
Example: User and Group to Application Roles Mapping
<app-role>
<name>EMP</name>
<display-name>Employee for dept #60 and dept #100</display-name>
<description>HR manager for dept #60 and representative for dept #100</description>
<guid>F917C3608CF011E2BF802D569259982</guid>
<class>oracle.security.jps.service.policystore.ApplicationRole</class>
<members>
<member>
<class>weblogic.security.principal.WLSUserImpl</class>
<name>LPOPP</name>
</member>
</members>
</app-role>
About the HR Demo (1) - Logged in as Employee LPOPP
Session Service HR Demo(1) Logged in as Employee LPOPP displays employee records that you can access logged in as an employee, LPOPP. You can see everyone’s record except their salary information, you can see your own salary information, and you can update your own contact information.
This access is set by:
-
Realm and grant (1):
DEPARTMENT_ID in (60, 100)andSELECT to EMP -
Realm and grant (2):
UPPER(email) = XS_SYS_CONTEXT("PROFILE_NS","EMAIL")andUPDATE, VIEW_SENSITIVE_INFO to EMP -
Column Constraints:
SALARYrequiresVIEW_SENSITIVE_INFOprivilege
Salary is only shown if you are authorized to view, and ID is shown as a link (Italic format in the table) if you are authorized to update.
Session Service HR Demo(1) Logged in as Employee LPOPP
| ID | First Name | Last Name | Phone | Salary | Department ID | Manager ID | |
|---|---|---|---|---|---|---|---|
| 103 | Alexander | Hunold | AHUNOLD | 510.222.3388 | ** | 60 | 102 |
| 104 | Bruce | Ernst | BERNST | 590.423.4568 | ** | 60 | 103 |
| 105 | David | Austin | DAUSTIN | 590.423.4569 | ** | 60 | 103 |
| 106 | Valli | Pataballa | VPATABAL | 590.423.4560 | ** | 60 | 103 |
| 107 | Diana | Lorentz | DLORENTZ | 590.423.4567 | ** | 60 | 103 |
| 108 | Nancy | Greenberg | NGREENBE | 515.124.4569 | ** | 100 | 101 |
| 109 | Daniel | Faviet | DFAVIET | 515.124.4169 | ** | 100 | 108 |
| 110 | John | Chen | JCHEN | 515.124.4269 | ** | 100 | 108 |
| 111 | Ismael | Sciarra | ISCIARRA | 515.124.4369 | ** | 100 | 108 |
| 112 | Jose Manuel | Urman | JMURMAN | 515.124.4469 | ** | 100 | 108 |
| 113 | Luis | Popp | LPOOP | 133.444.5555 | 6900 | 100 | 108 |
About the HR Demo (2) - Logged in as HRMGR
Session Service HR Demo(2) Logged in as HR Manager HRMGR displays employee records that you can access logged in as an HR Manager, HRMGR. You can see every employee’s salary information, and you can update every employee’s contact information.
This access is set by the realm and grant: DEPARTMENT_ID in (60, 100), SELECT, UPDATE, and VIEW_SENSITIVE_INFO to HRMGR.
Salary is only shown if you are authorized to view, and ID is shown as a link (Italic format in the table) if you are authorized to update.
Session Service HR Demo(2) Logged in as HR Manager HRMGR
| ID | First Name | Last Name | Phone | Salary | Department ID | Manager ID | |
|---|---|---|---|---|---|---|---|
| 103 | Alexander | Hunold | AHUNOLD | 510.222.3388 | 9000 | 60 | 102 |
| 104 | Bruce | Ernst | BERNST | 590.423.4568 | 6000 | 60 | 103 |
| 105 | David | Austin | DAUSTIN | 590.423.4569 | 4800 | 60 | 103 |
| 106 | Valli | Pataballa | VPATABAL | 590.423.4560 | 4800 | 60 | 103 |
| 107 | Diana | Lorentz | DLORENTZ | 590.423.4567 | 4200 | 60 | 103 |
| 108 | Nancy | Greenberg | NGREENBE | 515.124.4569 | 12008 | 100 | 101 |
| 109 | Daniel | Faviet | DFAVIET | 515.124.4169 | 9000 | 100 | 108 |
| 110 | John | Chen | JCHEN | 515.124.4269 | 8200 | 100 | 108 |
| 111 | Ismael | Sciarra | ISCIARRA | 515.124.4369 | 7700 | 100 | 108 |
| 112 | Jose Manuel | Urman | JMURMAN | 515.124.4469 | 7800 | 100 | 108 |
| 113 | Luis | Popp | LPOOP | 133.444.5555 | 6900 | 100 | 108 |
About the HR Demo (3) - Logged in as a Team Manager
Session Service HR Demo(3) Logged in as Team Manager AHUNOLD displays employee records that you can access logged in as a Team Manager, AHUNOLD. You can see your team member’s salary information; however, you cannot update their contact information, only your own contact information.
This access is set by the realm and grant: is my member(employee_id) =1 and VIEW_SENSITIVE_INFO to EMP.
Salary is only shown if you are authorized to view, and ID is shown as a link (Italic format in the table) if you are authorized to update.
Session Service HR Demo(3) Logged in as Team Manager AHUNOLD
| ID | First Name | Last Name | Phone | Salary | Department ID | Manager ID | |
|---|---|---|---|---|---|---|---|
| 103 | Alexander | Hunold | AHUNOLD | 510.222.3388 | 9000 | 60 | 102 |
| 104 | Bruce | Ernst | BERNST | 590.423.4568 | 6000 | 60 | 103 |
| 105 | David | Austin | DAUSTIN | 590.423.4569 | 4800 | 60 | 103 |
| 106 | Valli | Pataballa | VPATABAL | 590.423.4560 | 4800 | 60 | 103 |
| 107 | Diana | Lorentz | DLORENTZ | 590.423.4567 | 4200 | 60 | 103 |
| 108 | Nancy | Greenberg | NGREENBE | 515.124.4569 | ** | 100 | 101 |
| 109 | Daniel | Faviet | DFAVIET | 515.124.4169 | ** | 100 | 108 |
| 110 | John | Chen | JCHEN | 515.124.4269 | ** | 100 | 108 |
| 111 | Ismael | Sciarra | ISCIARRA | 515.124.4369 | ** | 100 | 108 |
| 112 | Jose Manuel | Urman | JMURMAN | 515.124.4469 | ** | 100 | 108 |
| 113 | Luis | Popp | LPOOP | 133.444.5555 | ** | 100 | 108 |