Oracle® Containers for J2EE Security Guide 10g (10.1.3.5.0) Part Number E13977-01 |
|
|
View PDF |
This chapter discusses login modules supplied with OC4J, as well as how to implement, install, and configure a custom login module. The following topics are covered:
Configuring the Custom Security Provider in Application Server Control
Using Admintool to Configure Login Modules and Grant RMI Permission
Summary of Login Module Configuration in OC4J Configuration Files
See Also:
This section covers the following:
By default, OC4J specifies usage of the OracleAS JAAS Provider login configuration provider (oracle.security.jazn.spi.LoginConfigProvider
) by the OC4J JVM, overriding usage of the Sun Microsystems default JAAS login configuration provider.
This is accomplished through the following configuration in the file ORACLE_HOME
/j2ee/home/config/jazn.security.props
:
login.configuration.provider=oracle.security.jazn.spi.LoginConfigProvider
The Oracle login configuration provider uses the system-jazn-data.xml
file for login module configuration.
Be aware of the following notes regarding the use of login modules with OC4J:
By convention, a setting of provider="XML"
is required for an application using custom login modules (custom security provider). See related information about the custom.loginmodule.provider
property in "Settings in <jazn> for Login Modules".
When using custom login modules, it is possible to instruct the OracleAS JAAS Provider to base authorization checks on the authenticated subject instead of basing checks on the users and roles defined in system-jazn-data.xml
or the application-specific jazn-data.xml
file. See related information about the role.mapping.dynamic
property in "Settings in <jazn> for Login Modules".
To ensure that all relevant principals are taken into consideration during authorization, the login module must add the relevant principals (including any roles that the authenticated user belongs to) to the subject during the commit
phase of the authentication process.
Login module configuration (under the <jazn-loginconfig>
element) cannot be in an application-specific jazn-data.xml
file; it must be in system-jazn-data.xml
. Configuration will be written to system-jazn-data.xml
automatically if you configure login modules through Application Server Control or in your orion-application.xml
file. (Also see "Settings in <jazn-loginconfig> in orion-application.xml".)
If you use any identity repository other than the file-based provider or Oracle Internet Directory, you must define an administrative user account and administrator roles, grant the roles to the user, and grant necessary permissions to the roles, as discussed in "Creating the Administrative User and Roles and Granting RMI Permission".
Because the JAAS specification does not cover user management, when you configure your application to use a custom login module, the use of the UserManager
API within your application is not supported. The J2EE API, however, will continue to function within your application.
See "OracleAS JAAS Provider Policy Management" regarding subject-based policy management when using a custom login module. The policy configuration must be in system-jazn-data.xml
.
"Using the File-Based Provider Across an OC4J Group" discusses how to maintain system-jazn-data.xml
settings across multiple OC4J instances. This functionality also applies to login modules, using MBean operations such as setLoginModule
, remLoginModule
, and getLoginModuleControlFlagTypes
.
If an application is configured to use a custom login module but the login module is not found in the classpath, a "class not found" exception is thrown with a message such as the following: "WARNING unable to find LoginModule class: Missing class: Xxxxxx..." See "Summary of Choices for Packaging Login Modules" for related information.
Be aware that when you use a custom login module, role comparisons for authorization are not case-sensitive unless you add the following property setting to the <jazn>
element in orion-application.xml
:
<property name="role.compare.ignorecase" value="false" />
OC4J supplies the set of login modules, including standard J2EE login modules, listed in Table 9-1.
Table 9-1 Login Modules Supplied with OC4J
Login Module | Description |
---|---|
oracle.security.jazn.login.module. RealmLoginModule |
OC4J login module for the file-based provider or Oracle Identity Management. (Additional information follows.) |
oracle.security.jazn.login.module.db. DBTableOraDataSourceLoginModule |
OC4J login module for user data in a database. (Additional information follows.) |
oracle.security.jazn.login.module. LDAPLoginModule |
OC4J login module for external LDAP providers. |
oracle.security.jazn.login.module.coreid. CoreIDLoginModule |
OC4J login module for Oracle Access Manager. See Also: Chapter 11, "Oracle Access Manager" |
Notes:
This table does not show additional login modules internal to OC4J.
Oracle does not currently validate Sun login modules for use with OC4J. (These login modules, in package com.sun.security.auth.module
, are not currently part of the JDK.)
This rest of this section offers additional information about the following login modules:
The RealmLoginModule
class is the default login module, for use with the file-based provider or Oracle Identity Management, and is configured when you configure these security providers through Application Server Control. This configuration is reflected in a <login-module>
element under <jazn-loginconfig>
in the system-jazn-data.xml
file.
The RealmLoginModule
class authenticates user login credentials before the user can access J2EE applications. Authentication is performed using OC4J container-based authentication (HTTP basic, form-based, and so on).
RealmLoginModule
supports the options shown in Table 9-2 (reflected in <name>
and <value>
subelements of an <option>
element under <login-module>
).
Table 9-2 RealmLoginModule Options
Option | Description | Default |
---|---|---|
debug |
If set to |
false |
addRoles |
If set to |
true |
addAllRoles |
If set to |
true |
storePrivateCredentials |
If set to |
false |
supportNullPassword |
(Oracle Identity Management only) If set to |
false |
Notes:
RealmLoginModule
does not have to be enabled if your application uses Oracle Single Sign-On authentication.
RealmLoginModule
is used only with declarative security, not programmatic security.
The use of RealmLoginModule
as a custom login module—in other words, as a custom security provider—is not supported.
See Also:
"Using Admintool to Configure Login Modules and Grant RMI Permission" for information on using the Admintool
Here is sample configuration of RealmLoginModule
, in system-jazn-data.xml
. (We recommend that you not alter RealmLoginModule
configuration manually; this example is just for illustrative purposes.)
<jazn-loginconfig> <application> <name>oracle.security.jazn.tools.Admintool</name> <login-modules> <login-module> <class>oracle.security.jazn.realm.RealmLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>debug</name> <value>false</value> </option> <option> <name>addAllRoles</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> <application> <name>oracle.security.jazn.oc4j.JAZNUserManager</name> <login-modules> <login-module> <class>oracle.security.jazn.realm.RealmLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>addAllRoles</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig>
The OC4J 10.1.3.1 implementation supplies a login module you can use if you have a user identity store in a database:
oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule
This replaces previous functionality of the com.evermind.sql.DataSourceUserManager
class, now deprecated (but still supported for backward compatibility, and still documented at the end of this section for completeness). It also replaces some authentication functionality of the deprecated com.evermind.security.User
class.
Once you have created your database schema and an Oracle data source to connect to the database (as described in the data sources chapter of the Oracle Containers for J2EE Services Guide), you are ready to configure the login module.
DBTableOraDataSourceLoginModule
supports a number of options for specifying such items as data location (table and column names) and password encryption. You can set these options through Application Server Control or the OracleAS JAAS Provider Admintool, with the settings being reflected in the <jazn-loginconfig>
element of the system-jazn-data.xml
file.
This section covers the following topics:
Configuring DBTableOraDataSourceLoginModule in Application Server Control
Configuring DBTableOraDataSourceLoginModule in the Admintool
Sample DBTableOraDataSourceLoginModule Settings in system-jazn-data.xml
Implementing DBLoginModuleEncodingInterface for Password Encryption
Note:
DBTableOraDataSourceLoginModule
is available with the OC4J product and automatically included in the classpath.Table 9-3 summarizes the options supported by DBTableOraDataSourceLoginModule
, noting which options are required, and including default values as applicable and examples as appropriate. There is no configuration of this login module in OC4J as shipped; refer to the sections that follow, "Configuring DBTableOraDataSourceLoginModule in Application Server Control" and "Configuring DBTableOraDataSourceLoginModule in the Admintool", for information about tools you can use in configuring the login module.
Note that DBTableOraDataSourceLoginModule
supports encrypted passwords in the database table, and you can use custom password encryption algorithms. To use this feature, you must use an implementation of the following interface, discussed in "Implementing DBLoginModuleEncodingInterface for Password Encryption":
oracle.security.jazn.login.module.db.DBLoginModuleEncodingInterface
Oracle supplies implementations for the SHA1 and MD5 algorithms.
Table 9-3 DBTableOraDataSourceLoginModule Options
Option | Description |
---|---|
data_source_name (required) |
Name of the data source for the database, as configured in the Default: n/a Example: jdbc/OracleDS |
table (required) |
Name of the database table containing user authentication information (user names, passwords, and so on). Default: n/a Example: userinfo |
groupMembershipTableName (required) |
Name of the database table containing role information. Default: n/a Example: groupinfo |
usernameField (required) |
Name of the column containing user names, in the table specified in the Default: n/a Example: userName |
passwordField (required) |
Name of the column containing passwords, in the table specified in the Default: n/a Example: passWord |
pw_encoding_class |
Name of your password encryption class, if you use password encryption. (See the discussion immediately preceding this table.) Default: oracle.security.jazn.login.module.db.util. DBLoginModuleClearTextEncoder (no encryption) Example: oracle.security.jazn.login.module.db.util. DBLoginModuleSHA1Encoder See Also: "Implementing DBLoginModuleEncodingInterface for Password Encryption" |
pw_key |
The password encryption key, if you use password encryption. This key is accessed by the class specified in the Default: n/a Example: xyz |
groupMembershipGroupFieldName (required) |
Name of the column containing role names, in the table specified in the |
user_pk_column |
Column name for the primary key in the table specified in the Default: Value of the Example: userName |
roles_fk_column |
Column name for the foreign key in the table specified in the Default: Value of the Example: userName |
casing |
The case-sensitivity when comparing login user names to names in the database. Use Default: sensitive Example: toupper |
Notes:
It is permissible to use the same table for user information and role information; in other words, to specify the same table for the table
and groupMembershipTableName
options. Notice that in this scenario, however, each user can have only one role. It is typical, and advisable, to use separate tables.
DBTableOraDataSourceLoginModule
does not support null or empty passwords.
If you use password encryption, passwords are compared according to their encrypted values, not the unencrypted strings. When a user logging in types the password, it is encrypted according to the encrypting method of the class you specify in the pw_encoding_class
option, and compared to the encrypted password stored in the database. No attempt is made to decrypt the password stored in the database.
"Configuring the Custom Security Provider in Application Server Control" discusses how to specify and configure a custom login module during deployment, change to a custom login module after deployment, add a login module, or update a login module. You can use these procedures to configure DBTableOraDataSourceLoginModule
. The Application Server Control Console login module configuration page enables you to specify the login module class, and to specify names and values for any number of properties corresponding to the options documented in the preceding section, "DBTableOraDataSourceLoginModule Options".
As an alternative to using the Application Server Control Console, you can configure DBTableOraDataSourceLoginModule
through the OracleAS JAAS Provider Admintool. Use of the Admintool for login modules is discussed in "Using Admintool to Configure Login Modules and Grant RMI Permission".
Here is an example:
java -jar jazn.jar -addloginmodule application_name \ oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule \ required data_source_name="jdbc/OracleDS" roles_fk_column="username" \ table="userinfo" groupMembershipTableName="groupinfo" \ groupMembershipGroupFieldName="role" usernameField="username" \ user_pk_column="username" passwordField="password" casing="sensitive"
As with any login module, option settings and other configuration are stored within the <jazn-loginconfig>
element of the system-jazn-data.xml
file. Here is an example:
<jazn-loginconfig> <application> <name>application_name</name> <login-modules> <login-module> <class> oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule </class> <control-flag>required</control-flag> <options> <option> <name>data_source_name</name> <value>jdbc/OracleDS</value> </option> <option> <name>table</name> <value>userinfo</value> </option> <option> <name>roles_fk_column</name> <value>userName</value> </option> <option> <name>groupMembershipGroupFieldName</name> <value>role</value> </option> <option> <name>user_pk_column</name> <value>userName</value> </option> <option> <name>passwordField</name> <value>passWord</value> </option> <option> <name>groupMembershipTableName</name> <value>groupinfo</value> </option> <option> <name>usernameField</name> <value>userName</value> </option> <option> <name>casing</name> <value>sensitive</value> </option> </options> </login-module> </login-modules> </application> ... </jazn-loginconfig>
DBTableOraDataSourceLoginModule
uses the following principals:
oracle.security.jazn.login.module.db.principals.DBUserPrincipal
(for users)
oracle.security.jazn.login.module.db.principals.DBRolePrincipal
(for roles)
A subject passed to the DBTableOraDataSourceLoginModule
is populated with instances of these principal types.
For a user name in the user table (a name in the column indicated by the usernameField
option, in the table indicated by the table
option), there would be a corresponding DBUserPrincipal
instance in the subject.
For a role name in the role table (a name in the column indicated by the groupMembershipGroupFieldName
option, in the table indicated by the groupMembershipTableName
option), there would be a corresponding DBRolePrincipal
instance in the subject.
You can use the Admintool to grant permissions to a user or role, as follows:
% java -jar jazn.jar -grantperm \ oracle.security.jazn.login.module.db.principals.DBUserPrincipal name \ permissionclass [permission_parameters]
% java -jar jazn.jar -grantperm \ oracle.security.jazn.login.module.db.principals.DBRolePrincipal name \ permissionclass [permission_parameters]
In this syntax, name
is the name of the DBUserPrincipal
or DBRolePrincipal
instance, permissionclass
is the fully qualified name of the permission class for the permission you are granting, and permission_parameters
are any appropriate parameters of the permission class (login
for RMIPermission
, for example).
Important:
Ensure that permission classes are in the classpath.To use password encryption with DBTableOraDataSourceLoginModule
, you must use an implementation of the following interface to perform the encryption:
oracle.security.jazn.login.module.db.DBLoginModuleEncodingInterface
The implementing class must implement the following method, which is called by the login module:
String getKeyDigestString(String text, String key)
This method takes a text string to encrypt (such as a password) and a string that specifies a key, as set in the pw_key
option for the login module (if applicable). The method would then encrypt the text string with any desired algorithm (with the key if specified), and preferably also formats the post-encryption binary data using any desired encoding standard (Base64Encoding
, for example). It outputs the encrypted digest string.
For algorithms that do not use a key, such as MD5 or SHA1, any key passed could be ignored. If the pw_key
option is not set, then its value is null
and null
is passed.
Oracle provides the following implementations in the oracle.security.jazn.login.module.db.util
package:
DBLoginModuleSHA1Encoder
This class generates a hash value for the given password string using the SHA1 algorithm, and encodes the binary hash using Base64Encoding
. The binary hash of the password must be stored in the database using Base64Encoding
.
DBLoginModuleMD5Encoder
This class generates a hash value for the given password string using the MD5 algorithm, and encodes the binary hash using Base64Encoding
. The binary hash of the password must be stored in the database using Base64Encoding
.
DBLoginModuleClearTextEncoder
If you do not specify an encryption class, DBLoginModuleClearTextEncoder
is used, resulting in no encryption. This class simply passes the password string as it is given.
Prior to implementation of DBTableOraDataSourceLoginModule
in the OC4J 10.1.3.1 implementation, equivalent functionality was available through the com.evermind.sql.DataSourceUserManager
class. While this feature is currently still supported for backward compatibility, it is deprecated and will be desupported in future releases. You should use DBTableOraDataSourceLoginModule
instead.
However, for completeness, we include the following documentation for the DataSourceUserManager
feature.
Notes:
The database you use must be specified as a data source, for which you provide a JNDI location in your configuration. The configuration also specifies the relevant database tables and fields.
In OC4J 10.1.3.x implementations, DataSourceUserManager
obtains group information only from the database, which differs from the behavior in previous implementations. Therefore, you must map groups to users in the database, as applicable.
When you configure DataSourceUserManager
(as described shortly), you can specify values for the properties described in Table 9-4, as appropriate. The DataSourceUserManager
instance uses these properties to access the user-defined database table that lists the current users and their associated credentials.
Table 9-4 DataSourceUserManager Properties
Property | Description |
---|---|
dataSource |
A JNDI location for the installed data source (database) to use. |
table |
Name of the database table containing user data. |
usernameField |
Name of the column for user names in the database table. |
passwordField |
Name of the column for passwords in the database table. |
certificateIssuerField |
An identifier for the certificate issuer, if applicable. |
certificateSerialField |
The serial ID of the certificate issuer, if applicable. |
localeField |
The locale, if applicable. |
defaultGroups |
Comma-delimited list of groups that the users are members of. |
groupMembershipTableName |
Name of an optional database table that maps users to groups, if the use of |
groupMembershipUserNameFieldName |
Name of the column for user names in the group membership database table, if applicable. |
groupMembershipGroupFieldName |
Name of the column for group names in the group membership database table, if applicable. |
staleness |
Number of milliseconds for which a fetched set of user data will be valid. The default setting is -1 (forever). |
casing |
Flag that controls how The default " |
debug |
Flag to enable output of debug information. |
To use DataSourceUserManager
, configure it in a <user-manager>
element in your orion-application.xml
file. This is a subelement of <orion-application>
, and must be configured manually. There is no UserManager
support in Application Server Control 10.1.3.x implementations.
Specify the DataSourceUserManager
fully qualified name in the class
attribute of <user-manager>
. Use a <property>
subelement to specify the name and value of each property you want to set.
Here is an example:
<orion-application ... > ... <user-manager class="com.evermind.sql.DataSourceUserManager"> <property name="dataSource" value="jdbc/OracleCoreDS" /> <property name="table" value="j2ee_users" /> <property name="usernameField" value="username" /> <property name="passwordField" value="password" /> <property name="groupMembershipTableName" value="second_table" /> <property name="groupMembershipGroupFieldName" value="group" /> <property name="groupMembershipUserNameFieldName" value="userId" /> </user-manager> ... </orion-application>
Because OC4J support for JAAS fully complies with the JAAS 1.0 specification, users can plug in any JAAS-compliant LoginModule
implementation, if desired. (OC4J includes the RealmLoginModule
class as its default login module implementation. This class combines J2EE security constraints with either the file-based provider or Oracle Identity Management.)
A custom login module may be desirable, for example, when users and roles are defined in an external repository. When you create a custom login module, consider the following preliminary questions:
Development: Do you want to take advantage of J2EE security constraints?
Debugging: Do you want the login module to support a debugging option for use during development? (As noted previously, RealmLoginModule
, for example, supports a debug
option that provides diagnostic output. Also, "Custom Login Module Example" includes debugging functionality.)
Packaging and deployment: Are you using login modules that come with OC4J or J2SE 1.4? Or are you deploying custom or third-party login modules? And are you packaging the login modules with your application, or making them available separately as an optional package or library?
When you associate a custom login module with an application (through configuration, as shown later), the subject and the principals it contains are used as the sole basis for all authorization tasks, including evaluating J2EE security constraints. To ensure that all relevant principals are considered during authorization, the login module must add the relevant principals, including all roles that the authenticated user participates in, to the subject during the commit phase of the authentication process. (The role.mapping.dynamic
property, discussed in "Settings in <jazn> for Login Modules", is related to subject-based authorization.)
The custom login module framework supports the J2EE declarative security model. This means that subject-based authorization enforces the J2EE security constraints declared in application deployment descriptors (web.xml
and ejb-jar.xml
, for example).
Custom login modules are configured through the OC4J system-jazn-data.xml
file, which can be updated automatically through use of tools such as Application Server Control Console and OracleAS JAAS Provider Admintool. You can also configure login modules through orion-application.xml
, in which case the configuration is copied to system-jazn-data.xml
.
See Also:
Sun Microsystems JAAS documentation for general information about developing custom login modules:
http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html
If you are using one or more of the default login modules provided with OC4J or the J2SE, then no additional configuration is needed. The OracleAS JAAS Provider can locate the default login modules.
If you are deploying your application with one or more custom login modules, then you must deploy the login modules and configure the OracleAS JAAS Provider properly so that the module can be found at runtime. The following sections discuss ways to accomplish this:
The remainder of this section discusses these options in greater detail.
Important:
If an application is configured to use a custom login module but the login module is not found in the classpath, a "class not found" exception is thrown with a message such as the following: "WARNING unable to find LoginModule class: Missing class: Xxxxxx..."If your login modules are used by only a single J2EE application, then you can simply package the login modules as part of your application by including the login module JAR file in the application EAR file.
The login modules must be configured through <jazn-loginconfig>
settings, in one of two places:
In the system-jazn-data.xml
file, as discussed in "Login Module Settings in system-jazn-data.xml"
In the orion-application.xml
file in your application EAR file, as discussed in "Settings in <jazn-loginconfig> in orion-application.xml"
Using the Application Server Control Console, you can configure custom login modules as you deploy an application, or later if you change the security provider to custom. This results in system-jazn-data.xml
being updated automatically.
Administering custom login modules through the OracleAS JAAS Provider Admintool will also update system-jazn-data.xml
settings for you.
Note:
If a different application needs the same login module, you must repackage the login module and any relevant classes with the new application, or make it available as an optional package or shared library.If you deploy your login modules as an optional package (formerly known as a "standard extension"), the OracleAS JAAS Provider will be able to find them. No additional configuration is necessary. Deploying login modules as an optional package allows multiple applications to share them.
There are two ways to use the optional package mechanism:
Use the login module classes as an installed optional package. Place the login module JAR file in the jre/lib/ext
directory. Classes in JAR files in this directory can be used by applications without having to be included in the classpath.
Use the login module classes as a download optional package. Specify the login module JAR file in the Class-Path
header field in the manifest of other JAR files, as desired. In this way, classes in the login module JAR file can be used by classes in the other JAR files that reference it.
The login modules must also be configured in system-jazn-data.xml
, as discussed in "Login Module Settings in system-jazn-data.xml".
See Also:
For general information about the standard "optional package" mechanism:
http://java.sun.com/j2se/1.4.2/docs/guide/extensions
The OracleAS JAAS Provider is integrated with the OC4J class loading architecture. Because of this, you can make login modules available to applications by loading them as OC4J shared libraries, as documented in "Tasks to Share a Library".
This section discusses the following administration tasks for the custom security provider (custom login modules) using the Application Server Control Console:
Notes:
Procedures discussed throughout this section assume you are logged in to Application Server Control as a user with required administrative permissions (as oc4jadmin
, for example).
Any login module you specify must be in the classpath at runtime. (One option is to load it as a shared library, as described in "Tasks to Share a Library".)
Custom login modules must not be named other
, ascontrol
, and default
. These names are reserved for the predefined JAAS login modules.
When you plan to use a custom security provider and you deploy an application through Application Server Control, you have the opportunity to configure your custom login modules during deployment.
From the Deploy: Deployment Settings page (see "Deploying an Application through Application Server Control" for how to get to this page):
Go to the Select Security Provider task.
In the resulting Deployment Settings: Select Security Provider page, choose Custom from the Security Provider dropdown list.
Under "Configuration of Custom Security Provider" (which appears after you choose Custom), you can edit or delete any custom login module that is found with your application, or add a new custom login module.
To add a new custom login module, choose Add Login Module. See "Adding a Custom Login Module during Deployment".
To edit an existing custom login module, choose the Edit task for the appropriate module. See "Editing a Custom Login Module Configuration during Deployment".
To delete an existing custom login module, choose the Delete task for the appropriate module.
Still in the Deployment Settings: Select Security Provider page, choose OK to finish the security provider selection.
Back in the Deploy: Deployment Settings page, choose Deploy to complete the deployment, or choose another task, as desired. The list of tasks is noted in "Deploying an Application through Application Server Control".
Deploying or configuring a custom login module through Application Server Control results in the following required settings being inserted automatically in the orion-application.xml
file:
<jazn provider="XML"> <property name="role.mapping.dynamic" value="true" /> <property name="custom.loginmodule.provider" value="true" /> </jazn>
Notes:
Grants for custom login modules, which are stored in system-jazn-data.xml
, cannot be configured through Application Server Control.
By convention, there is a <jazn>
setting of provider="XML"
when you use custom login modules.
Custom login module configuration settings are reflected under the <jazn-loginconfig>
element in the system-jazn-data.xml
file, as shown in "Login Module Settings in system-jazn-data.xml".
See Also:
"Summary of Login Module Configuration in OC4J Configuration Files" and "Step by Step: Integrating a Custom Login Module with OC4J" for information and examples regarding the resulting XML configuration for login modules
To edit a custom login module while deploying an application using the Custom Security Provider, take the following steps, starting under "Configuration of Custom Security Provider" in the Deployment Settings: Select Security Provider page (see earlier in "Specifying and Configuring a Custom Security Provider during Deployment" for how to get to this point):
Choose the Edit task for the appropriate login module in the list of login module classes.
In the Deployment Settings: Select Security Provider: Edit Login Module page:
Specify a value for the login module control flag (from the dropdown list): Required, Requisite, Optional, or Sufficient. Table 9-5 describes these settings.
As desired, choose Add Another Row to create properties.
As desired, edit the name or value of any property in the Properties list.
As desired, use the Delete task for a property to remove that property.
Choose Continue to go back to the Deployment Settings: Select Security Provider page to continue the deployment steps in "Specifying and Configuring a Custom Security Provider during Deployment".
Table 9-5 Login Module Control Flags
Flag | Meaning |
---|---|
|
The login module is nominally required to succeed. Whether or not it succeeds, however, authentication proceeds down the login module list. |
|
The login module nominally must succeed. If it succeeds, authentication continues down the login module list. If it fails, control immediately returns to the application—authentication does not continue down the login module list. |
|
The login module is not required to succeed. If it succeeds, control immediately returns to the application, and authentication does not proceed down the login module list. If it fails, authentication continues down the login module list. |
|
The login module is not required to succeed. Whether or not it succeeds, authentication proceeds down the login module list. |
These control flag settings are used according to standard functionality of the javax.security.auth.login.Configuration
class. The overall authentication succeeds only if all "required" and "requisite" login modules succeed, possibly unless a "sufficient" login module is configured and succeeds—in that case, only the required and requisite login modules prior to the sufficient login module in the login module list must succeed.
To add a custom login module while deploying an application using the Custom Security Provider, take the following steps, starting under "Configuration of Custom Security Provider" in the Deployment Settings: Select Security Provider page (see earlier in "Specifying and Configuring a Custom Security Provider during Deployment" for how to get to this point):
Choose Add Login Module.
In the Deployment Settings: Select Security Provider: Add Login Module page:
Specify your login module package and class name.
Specify a value for the login module control flag (from the dropdown list): Required, Requisite, Optional, or Sufficient. See Table 9-5, "Login Module Control Flags" in the preceding section for information about these settings.
As desired, choose Add Another Row to create properties.
As desired, edit the name or value of any property in the Properties list.
As desired, use the Delete task for a property to remove that property.
Choose Continue to go back to the Deployment Settings: Select Security Provider page to continue the deployment steps in "Specifying and Configuring a Custom Security Provider during Deployment".
You can select a security provider for your application at deployment time, as described above. You can also change to a different security provider after deployment. You can change to a custom security provider as follows:
Go to the Security Provider page for your application, as described in "Navigating to the Security Provider Page for Your Application".
In the Security Provider page, choose Change Security Provider.
In the Change Security Provider page, select "Custom Security Provider" from the dropdown.
Under "Login Modules" (which appears after you select Custom Security Provider in the dropdown), specify the first login module to be used, as follows. Later you can go back to the Security Provider to add more login modules, as described in the next section, "Adding a Login Module to the Custom Security Provider".
Specify your login module package and class name.
Specify a value for the login module control flag (from the dropdown list)—Required, Requisite, Optional, or Sufficient. See Table 9-5, "Login Module Control Flags" for information about these settings.
As desired, choose Add Another Row to create properties.
As desired, edit the name or value of any property in the Properties list.
As desired, use the Delete task for a property to remove that property.
Choose OK to finish the change.
This takes you back to the Security Provider page, where you are prompted to restart your application for the changes to take effect.
Once you have established a custom security provider, either during or after deployment, you can add custom login modules as follows:
Note:
Custom login modules must not be namedother
, ascontrol
, and default
. These names are reserved for the predefined JAAS login modules.Go to the Security Provider page for your application, as described in "Navigating to the Security Provider Page for Your Application".
In the Security Provider page, under "Login Modules", choose Create.
In the Add Login Module page:
Specify your login module package and class name.
Specify a value for the login module control flag (from the dropdown list): Required, Requisite, Optional, or Sufficient. See Table 9-5, "Login Module Control Flags" for information about these settings.
As desired, choose Add Another Row to create properties.
As desired, edit the name or value of any property in the Properties list.
As desired, use the Delete task for a property to remove that property.
Choose OK to finish the change.
This takes you back to the Security Provider page, where you can examine the settings.
Once you have established a custom security provider, either during or after deployment, you can update custom login modules as follows:
Go to the Security Provider page for your application, as described in "Navigating to the Security Provider Page for Your Application".
In the Security Provider page, in the list of login module classes, choose the Edit task for the login module you want to update.
In the Edit Login Module page:
As desired, update the value for the login module control flag (from the dropdown list): Required, Requisite, Optional, or Sufficient. See Table 9-5, "Login Module Control Flags" for information about these settings.
As desired, choose Add Another Row to create properties.
As desired, edit the name or value of any property in the Properties list.
As desired, use the Delete task for a property to remove that property.
Choose Apply to finish the change.
This leaves you in the Edit Login Module page. You can use the breadcrumbs at the top of the page to go back to the Security Provider page.
Once you have established a custom security provider, either during or after deployment, you can delete custom login modules as follows:
Go to the Security Provider page for your application, as described in "Navigating to the Security Provider Page for Your Application".
In the Security Provider page, in the list of login module classes, choose the Delete task for the login module you want to delete.
Choose Yes in the Confirmation page.
This takes you back to the Security Provider page, where you can see that the login module was deleted.
This section describes how to use the OracleAS JAAS Provider Admintool in the following ways:
As an alternative to the Application Server Control Console for adding and configuring login modules
To grant RMI permission "login" to appropriate principals to access EJBs through RMI
Although Application Server Control is the preferred and recommended tool for adding and configuring custom login modules, it is also possible to use the OracleAS JAAS Provider Admintool. The following information is presented for reference:
-addloginmodule
: Configures a new login module for the named application. This includes specifying a control flag: one of required
, requisite
, sufficient
or optional
, as specified by javax.security.auth.login.Configuration
and in Table 9-5, "Login Module Control Flags".
If the login module supports options, specify each option and its value as an optionname=value
pair. Each login module has its own individual set of options.
For example, to add MyLoginModule
, which we will assume supports a debug
option, to the application myapp
as a required module with debug
set to true
:
% java -jar jazn.jar -addloginmodule myapp MyLoginModule required debug=true
-remloginmodule
: Removes the specified login module.
To remove MyLoginModule
from myapp
:
% java -jar jazn.jar -remloginmodule myapp MyLoginModule
-listloginmodules
: Displays all login modules for a specified application, or, if no application name is specified, displays login modules for all applications. Specifying a login module class after the application name displays information on only the specified class within the application.
For example, to display all login modules for the application myapp
:
% java -jar jazn.jar -listloginmodules myapp
You can also execute these commands from the Admintool shell.
Important:
Restart OC4J for changes to take effect.In case your application includes EJBs, note that to access an EJB through RMI, you must grant RMI permission "login" to the appropriate user, role, or principal. You can accomplish this through the Admintool, as in the following examples:
% java -jar jazn.jar -grantperm myrealm -role managers \ com.evermind.server.rmi.RMIPermission login % java -jar jazn.jar -grantperm oracle.security.jazn.samples.SamplePrincipal \ managers com.evermind.server.rmi.RMIPermission login
(Always specify a realm when granting permissions to a user or role, but not when granting permissions to a principal.)
If you are in an Oracle Application Server environment with multiple OC4J instances, then you must specify the appropriate instance name (and hence the appropriate home directory) for the applicable OC4J instance, so that the system-jazn-data.xml
file for the appropriate OC4J instance is updated. Set %oracleas.oc4j.instance%
appropriately for your environment.
% java -jar -Doracle.j2ee.home=%ORACLE_HOME%/j2ee/%oracleas.oc4j.instance% \ jazn.jar -grantperm myrealm -role managers \ com.evermind.server.rmi.RMIPermission login % java -jar -Doracle.j2ee.home=%ORACLE_HOME%/j2ee/%oracleas.oc4j.instance% \ jazn.jar -grantperm oracle.security.jazn.samples.SamplePrincipal managers \ com.evermind.server.rmi.RMIPermission login
Important:
Restart OC4J for changes to take effect.See Also:
This section discusses files that contain configuration for custom login modules:
The system-jazn-data.xml
file is the repository for login module configuration.
Note that settings in system-jazn-data.xml
are updated automatically when you administer login modules through Application Server Control or the OracleAS JAAS Provider Admintool.
Note:
Where there are multiple OC4J instances, login module configuration is added to the instance-specificsystem-jazn-data.xml
file, not ORACLE_HOME
/j2ee/home/system-jazn-data.xml
.The <jazn-loginconfig>
element contains information that associates applications with login modules.
If this information is in the orion-application.xml
file during deployment, as discussed in "Settings in <jazn-loginconfig> in orion-application.xml", the system-jazn-data.xml
file will be updated accordingly.
Example 9-1 Example jazn-loginconfig element
<jazn-data> .. <jazn-loginconfig> <application> <name>myapp</name> <login-modules> <login-module> <class>mypath.MyLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>myoptionname</name> <value>myoptionvalue</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig> .. </jazn-data>
This fragment associates the login module MyLoginModule
with the application myapp
.
Note:
Do not remove login configuration information forRealmLoginModule
from the system-jazn-data.xml
file.See Also:
This section discusses particular settings for login modules in the OC4J application-level descriptor orion-application.xml
. The following topics are covered:
See Also:
Oracle Containers for J2EE Developer's Guide for general reference information about orion-application.xml
Settings in the <jazn-loginconfig>
element in system-jazn-data.xml
were documented in "Login Module Settings in system-jazn-data.xml". You can add this element to orion-application.xml
prior to deployment, and the settings will be written to the system-jazn-data.xml
file automatically. In addition, when you undeploy the application, the <jazn-loginconfig>
settings will be removed from system-jazn-data.xml
automatically.
The following <jazn>
properties are specific to login module configuration:
role.mapping.dynamic
This property, when set to true
, instructs the OracleAS JAAS Provider to base authorization checks on the authenticated subject instead of basing checks on the users and roles defined in system-jazn-data.xml
or the application-specific jazn-data.xml
file.
A LoginModule
instance must ensure that the appropriate principals (users or roles) are associated with the Subject
instance during the commit phase of the authentication process, in order for the principals to be taken into consideration during the authorization process. This association of principals to the subject is typically implemented using the standard JAAS API.
custom.loginmodule.provider
This property, when set to true
, instructs Application Server Control that the security provider is the custom provider. Without this setting, because the custom security provider uses the setting provider="XML"
, Application Server Control would mistakenly report that the security provider is the file-based provider (although custom login modules you provide in your EAR file would still work).
These properties are automatically set to "true
" in orion-application.xml
, as shown in the following example, when you have a <jazn-loginconfig>
element in orion-application.xml
, or when you deploy and configure your custom login module using the Application Server Control Console as discussed in "Specifying and Configuring a Custom Security Provider during Deployment".
<jazn provider="XML" ... > <property name="role.mapping.dynamic" value="true" /> <property name="custom.loginmodule.provider" value="true" /> </jazn>
If an application contains an EJB, remote clients must be given namespace access to read (look up) and write (bind) objects as required on the server-side JNDI context of the application.
The following example, which would appear in orion-application.xml
, shows how the namespace access is granted for read operations to roles named managers
and developers
.
<orion-application ... > ... <namespace-access> <read-access> <namespace-resource root=""> <security-role-mapping name="sr_developer"> <group name="developers"/> </security-role-mapping> <security-role-mapping name="sr_manager"> <group name="managers"/> </security-role-mapping> </namespace-resource> </read-access> </namespace-access> ... </orion-application>
This assumes the indicated role mappings had already been set up elsewhere in orion-application.xml
.
See Also:
For login modules, JAZN sets the mapping attribute for the Oracle Internet Directory (OID) provider to "DN"
by default.
To change the default value, you can configure the value of the mapping.attribute
property:
Locate the $Oracle_Home/j2ee/<oc4j_inst>/config/jazn.xml
file.
Add the mapping.attribute
property configuration to the <jazn> tag. For example:
<jazn provider... > ... <property name = "mapping.attribute" value="cn"/> ... </jazn>
Restart the OC4J instance.
The login modules that rely on the mapping.attribute
attribute in the jazn.xml
file, include:
WS-Security Username token with no password (WSSLoginModule
)
SAML (SAMLLoginModule
)
SAMLLoginModule
first looks at the SubjectNameIdentifier
to determine the mapping. If blank, then the mapping.attribute
is used.
X.509 client certificate authentication (X509LoginModule
)
Third party login module (LDAPLoginModule
)
The mapping attribute for these login modules must be set in the jazn.xml
file as described here.
When you configure resource adapters, each <connector-factory>
element in the oc4j-ra.xml
file can specify a different JAAS login module, as in the following example. This also shows <config-property>
setup to connect to a database through Oracle JDBC.
<oc4j-connector-factories ... > ... <connector-factory connector-name="myBlackbox" location="eis/myEIS1"> <config-property name="connectionURL" value="jdbc:oracle:thin:@localhost:5521/myservice" /> <security-config use="jaas-module"> <jaas-module> <jaas-application-name>JAASModuleDemo</jaas-application-name> </jaas-module> </security-config> </connector-factory> ... </oc4j-connector-factories>
See Also:
Oracle Containers for J2EE Resource Adapter Administrator's Guide for additional information about configuring resource adapters
Developing a login module follows the standard development, packaging, and deployment cycle. For applications with EJBs, you must also grant RMI permission and configure namespace access as necessary. The following sections discuss each step in the cycle:
Develop a JAAS-compliant LoginModule
implementation according to the JAAS service provider interface.
When a login module is associated with an application (which occurs in the <jazn-loginconfig>
configuration shown earlier), OC4J uses the principals set in the subject to determine if the client has access to the requested J2EE resource. Thus, it is imperative that the login module correctly set all the roles the user is a member of.
In the following example, the login module authenticates the developer
user. After the user is successfully authenticated, a principal corresponding to the roles associated with the user is added to the current authenticated subject. Assume the developer
user is a member of the developers
role.
if(username.equals("developer") && password.equals("welcome")) { _succeeded = true; _name = "developer"; _password = password.toCharArray(); _authPrincipals = new SamplePrincipal[2]; //Adding username as principal to the subject _authPrincipals[0] = new SamplePrincipal("developer"); //Adding role developers to the subject _authPrincipals[1] = new SamplePrincipal("developers"); }
See Also:
javax.security.auth.spi.LoginModule
Javadoc:
http://java.sun.com/j2se/1.4.2/docs/api/
"Summary of Choices for Packaging Login Modules" summarizes the various ways you can package a login module so that it is accessible to your application. The choices are:
Package the login module with the application.
Provide the login module as an optional package.
Provide the login module as an OC4J shared library.
There are also choices for how you can specify the configuration of a login module:
Manually configure the <jazn-loginconfig>
element in your orion-application.xml
file, as discussed in "Settings in <jazn-loginconfig> in orion-application.xml". This may be particularly appropriate if you are packaging the login module with your application. The <jazn-loginconfig>
element in system-jazn-data.xml
is updated accordingly.
Use the Application Server Control Console to specify the login module settings, such as when you deploy your application, as discussed in "Configuring the Custom Security Provider in Application Server Control". The <jazn-loginconfig>
element in system-jazn-data.xml
is configured automatically.
Use the OracleAS JAAS Provider Admintool to specify the login module settings, as discussed in "Using Admintool to Configure Login Modules and Grant RMI Permission". The <jazn-loginconfig>
element in system-jazn-data.xml
is configured automatically.
The following sections highlight key configuration details.
OC4J requires the following configuration in the orion-application.xml
file in order to use a custom login module to perform security checks. This occurs automatically when you specify login module configuration through Application Server Control or in orion-application.xml
.
<jazn provider="XML" > <property name="role.mapping.dynamic" value="true"/> <property name="custom.loginmodule.provider" value="true"/> </jazn>
You can examine the orion-application.xml
file after deployment to confirm this.
The following configuration is for the sample login module shown in "Custom Login Module Example".
<!-- Configuring a Login Module in an Application EAR file. --> <jazn-loginconfig> <application> <name>cutomjaas</name> <login-modules> <login-module> <class>oracle.security.jazn.samples.SampleLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>debug</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig>
You could manually put this configuration into the orion-application.xml
file before deployment, or set the parameters (class name, control flag, and option names and values) as prompted during deployment when you deploy your application through Application Server Control. In either case, the configuration will automatically be written to system-jazn-data.xml
.
Configure namespace access in orion-application.xml
if the application includes any EJBs. This is to allow remote client access to JNDI bindings for read (lookup) or write (bind) operations as required on objects in the server-side JNDI context of the application. The following example shows how the namespace access is granted to roles named managers
and developers
.
<orion-application ... > ... <namespace-access> <read-access> <namespace-resource root=""> <security-role-mapping name="sr_developer"> <group name="developers"/> </security-role-mapping> <security-role-mapping name="sr_manager"> <group name="managers"/> </security-role-mapping> </namespace-resource> </read-access> </namespace-access> ... </orion-application>
This assumes the role mappings—mapping logical roles defined in the application to roles supported by the custom login module—have been properly defined, as in the following example from orion-application.xml
:
<orion-application ... > ... <!-- Mapping the logical roles to the container roles --> <security-role-mapping name="sr_manager"> <group name="managers" /> </security-role-mapping> <security-role-mapping name="sr_developer"> <group name="developers" /> </security-role-mapping> ... </orion-application>
You can specify role mappings through Application Server Control, as discussed in "Mapping Security Roles". This results in the orion-application.xml
entries being added automatically.
"Summary of Choices for Packaging Login Modules" discusses how you can deploy your login module either with your application or separately (as an optional package or shared library).
"Specifying and Configuring a Custom Security Provider during Deployment" discusses how to configure and deploy your login module through Application Server Control when you deploy your application.
If your application includes EJBs, be aware that to access an EJB through RMI, you must grant RMI permission "login" to the appropriate users, roles, and principals. You can accomplish this through the Admintool, as shown in "Granting RMI Permission through the Admintool".
To access resources through JNDI, you must configure the jndi.properties
file to set properties such as the provider URL, principal, and credential, as appropriate for your environment. Here is an example:
java.naming.factory.initial= oracle.j2ee.naming.ApplicationClientInitialContextFactory java.naming.provider.url=ormi://localhost:23791/customjaas #java.naming.provider.url=opmn:ormi://localhost:6003:home/customjaas java.naming.security.principal=manager java.naming.security.credentials=welcome
(The ormi
protocol is for standalone OC4J, while the opmn:ormi
protocol is for an Oracle Application Server environment. Uncomment the appropriate one.)
This section shows the login module code and principal code for an OC4J "how-to" example at the following location:
http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html
Look for the login module how-to under "J2EE Security / JAAS".
This section contains the code for the sample login module.
package oracle.security.jazn.samples; import java.util.Set; import java.util.Iterator; import java.util.Map; import java.security.Principal; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; public class SampleLoginModule implements LoginModule { // initial state protected Subject _subject; protected CallbackHandler _callbackHandler; protected Map _sharedState; protected Map _options; // configuration options protected boolean _debug; // the authentication status protected boolean _succeeded; protected boolean _commitSucceeded; // username and password protected String _name; protected char[] _password; protected Principal[] _authPrincipals; /* * Initialize this LoginModule. * * subject the Subject to be authenticated. * callbackHandler a CallbackHandler for communicating * with the end user (prompting for usernames and * passwords, for example). * sharedState shared LoginModule state. * options options specified in the login * Configuration for this particular * LoginModule. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this._subject = subject; this._callbackHandler = callbackHandler; this._sharedState = sharedState; this._options = options; // initialize any configured options _debug = "true".equalsIgnoreCase((String) _options.get("debug")); if (debug()) { printConfiguration(this); } } final public boolean debug() { return _debug; } protected Principal[] getAuthPrincipals() { return _authPrincipals; } /* * Authenticate the user by prompting for a username and password. * * return true if the authentication succeeded, or false if this * LoginModule should be ignored. * throws FailedLoginException if the authentication fails. * throws LoginException if this LoginModule * is unable to perform the authentication. */ public boolean login() throws LoginException { if (debug()) System.out.println("\t\t[SampleLoginModule] login"); if (_callbackHandler == null) throw new LoginException("Error: no CallbackHandler available " + "to garner authentication information from the user"); // Setup default callback handlers. Callback[] callbacks = new Callback[] { new NameCallback("Username: "), new PasswordCallback("Password: ", false) }; try { _callbackHandler.handle(callbacks); } catch (Exception e) { _succeeded = false; throw new LoginException(e.getMessage()); } String username = ((NameCallback)callbacks[0]).getName(); String password = new String(((PasswordCallback)callbacks[1]).getPassword()); if (debug()) { System.out.println("\t\t[SampleLoginModule] username : " + username); } // Authenticate the user. On successfull authentication add principals // to the Subject. The name of the principal is used for authorization by // OC4J by mapping it to the value of the name attribute of the group // element in the security-role-mapping for the application. if(username.equals("developer") && password.equals("welcome")) { _succeeded = true; _name = "developer"; _password = password.toCharArray(); _authPrincipals = new SamplePrincipal[2]; //Adding username as principal to the subject _authPrincipals[0] = new SamplePrincipal("developer"); //Adding role developers to the subject _authPrincipals[1] = new SamplePrincipal("developers"); } if(username.equals("manager") && password.equals("welcome")) { _succeeded = true; _name = "manager"; _password = password.toCharArray(); _authPrincipals = new SamplePrincipal[3]; //Adding username as principal to the subject _authPrincipals[0] = new SamplePrincipal("manager"); //Adding roles developers and managers to the subject _authPrincipals[1] = new SamplePrincipal("developers"); _authPrincipals[2] = new SamplePrincipal("managers"); } if (username.equals("sirish") && password.equals("sirish")) { _succeeded = true; _password = password.toCharArray(); _name = "sirish"; _authPrincipals = new SamplePrincipal[1]; _authPrincipals[0] = new SamplePrincipal("sirish"); } ((PasswordCallback)callbacks[1]).clearPassword(); callbacks[0] = null; callbacks[1] = null; if (debug()) { System.out.println("\t\t[SampleLoginModule] success : " + _succeeded); } if (!_succeeded) throw new LoginException ("Authentication failed: Password does not match"); return true; } /* * This method is called if the LoginContext's * overall authentication succeeded * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules * succeeded). * * If this LoginModule's own authentication attempt * succeeded (checked by retrieving the private state saved by the * login method, then this method associates a * Principal with the Subject located in the * LoginModule. If this LoginModule's own * authentication attempted failed, then this method removes * any state that was originally saved. * * return true if this LoginModule's own login and commit * attempts succeeded, or false otherwise. * throws LoginException if the commit fails. */ public boolean commit() throws LoginException { try { if (_succeeded == false) { return false; } if (_subject.isReadOnly()) { throw new LoginException("Subject is ReadOnly"); } // add authenticated principals to the Subject if (getAuthPrincipals() != null) { for (int i = 0; i < getAuthPrincipals().length; i++) { if(!_subject.getPrincipals().contains(getAuthPrincipals()[i])) { _subject.getPrincipals().add(getAuthPrincipals()[i]); } } } // in any case, clean out state cleanup(); if (debug()) { printSubject(_subject); } _commitSucceeded = true; return true; } catch (Throwable t) { if (debug()) { System.out.println(t.getMessage()); t.printStackTrace(); } throw new LoginException(t.toString()); } } /* * This method is called if the LoginContext's * overall authentication failed. * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules * did not succeed). * * If this LoginModule's own authentication attempt * succeeded (checked by retrieving the private state saved by the * login and commit methods), * then this method cleans up any state that was originally saved. * * return false if this LoginModule's own login and/or commit attempts * failed, and true otherwise. * throws LoginException if the abort fails. */ public boolean abort() throws LoginException { if (debug()) { System.out.println ("\t\t[SampleLoginModule] aborted authentication attempt."); } if (_succeeded == false) { cleanup(); return false; } else if (_succeeded == true && _commitSucceeded == false) { // login succeeded but overall authentication failed _succeeded = false; cleanup(); } else { // overall authentication succeeded and commit succeeded, // but someone else's commit failed logout(); } return true; } protected void cleanup() { _name = null; if (_password != null) { for (int i = 0; i < _password.length; i++) { _password[i] = ' '; } _password = null; } } protected void cleanupAll() { cleanup(); if (getAuthPrincipals() != null) { for (int i = 0; i < getAuthPrincipals().length; i++) { _subject.getPrincipals().remove(getAuthPrincipals()[i]); } } } /* * Logout the user. * * This method removes the Principal * that was added by the commit method. * * return true in all cases since this LoginModule * should not be ignored. * throws LoginException if the logout fails. */ public boolean logout() throws LoginException { _succeeded = false; _commitSucceeded = false; cleanupAll(); return true; } // helper methods // protected static void printConfiguration(SampleLoginModule slm) { if (slm == null) { return; } System.out.println("\t\t[SampleLoginModule] configuration options:"); if (slm.debug()) { System.out.println("\t\t\tdebug = " + slm.debug()); } } protected static void printSet(Set s) { try { Iterator principalIterator = s.iterator(); while (principalIterator.hasNext()) { Principal p = (Principal) principalIterator.next(); System.out.println("\t\t\t" + p.toString()); } } catch (Throwable t) { } } protected static void printSubject(Subject subject) { try { if (subject == null) { return; } Set s = subject.getPrincipals(); if ((s != null) && (s.size() != 0)) { System.out.println ("\t\t[SampleLoginModule] added the following Principals:"); printSet(s); } s = subject.getPublicCredentials(); if ((s != null) && (s.size() != 0)) { System.out.println ("\t\t[SampleLoginModule] added the following Public Credentials:"); printSet(s); } } catch (Throwable t) { } } }
This section contains the code for the sample principal.
The login module sets the SamplePrincipal
instance in the current Subject
instance. To create the SamplePrincipal
instance, the login module directly invokes the SamplePrincipal
constructor, so the constructor is defined as public.
package oracle.security.jazn.samples; import java.security.Principal; /* * This class implements the Principal interface * and represents a Sample user. * * Principals such as this SamplePrincipal * may be associated with a particular Subject * to augment that Subject with an additional * identity. Authorization decisions can then be based upon * the Principals associated with a Subject. * */ public class SamplePrincipal implements Principal { private String _name = null; /* * Create a SamplePrincipal with a Sample username. * */ public SamplePrincipal(String name) { if (name == null) throw new NullPointerException("name cannot be null"); _name = name; } /* * Return a string representation of this SamplePrincipal. * */ public String getName() { return _name; } /* * Return a hash code for this SamplePrincipal. * */ public int hashCode() { return _name.hashCode(); } /* * Return a string representation of this SamplePrincipal. * */ public String toString() { return "[SamplePrincipal] : " + _name; } /* * Compares the specified Object with this SamplePrincipal * for equality. Returns true if the given object is also a * SamplePrincipal and the two SamplePrincipals * have the same username. * */ public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (!(o instanceof SamplePrincipal)) return false; SamplePrincipal that = (SamplePrincipal)o; if (this.getName().equals(that.getName())) return true; return false; } }