Skip Headers

Oracle® Application Server Containers for J2EE Security Guide
10g Release 2 (10.1.2)
Part No. B14013-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

10 Custom LoginModules

This chapter discusses how to write and install a LoginModule to be used with the OracleAS JAAS Provider. This chapter contains the following sections:


Note:

Because the JAAS specification does not cover user management, when you configure your application to use a custom LoginModule, the use of the UserManager API within your application is effectively disabled. The J2EE API, however, will continue to function within your application.

Overview of JAAS Login Modules

OC4J supplies a JAAS pluggable authentication framework that conforms to the JAAS standard. With this framework, an application server and any underlying authentication services remain independent from each other, and alternative authentication services can be plugged in through JAAS login modules without requiring modifications to the application server or application code.

Possible types of JAAS login modules include the following:

A JAAS login module can be developed by the customer or supplied by the provider of the EIS and resource adapter. A login module must implement the standard JAAS LoginModule interface, which includes methods to initialize the login module, authenticate a given subject (referred to as phase 1), commit or abort an authentication (referred to as phase 2), and sign off a subject.

OC4J passes an initiating-principal subject to a JAAS login module. Specifically, this is a Subject instance containing a Principal instance that represents the OC4J user (initiating principal), along with any public certificates. OC4J can pass a null Subject instance if there is no authenticated user (that is, if the OC4J user is anonymous). The initiating-principal subject is passed to the initialize() method of the JAAS login module.

The login() method of the JAAS login module (for phase 1 authentication) must, based on the initiating principal, find the corresponding resource principal and create a new credential (such as a PasswordCredential instance) for the resource principal. The resource principal and the credential are then added to the initiating-principal Subject instance through the JAAS login module commit() method. The resource credential is passed to the createManagedConnection() method of the ManagedConnectionFactory implementation that is provided by the resource adapter.

If a null Subject is passed, the JAAS login module is responsible for creating a new Subject instance containing the resource principal and the appropriate credential.

Prerequisites

Before working with custom LoginModules, you must verify that you are using the XML-based provider; the LDAP-based provider does not support custom LoginModules. After you have verified the provider, turn on dynamic role mapping; see Configuring Dynamic Role Mapping for details.

Configuring Dynamic Role Mapping

When you turn on dynamic role mapping, the OracleAS JAAS Provider performs authorization checks based on the current Subject instead of using static configurations. By default, dynamic role mapping is turned off, which means that the OracleAS JAAS Provider uses static configurations as the basis for authorization checks.

To turn on dynamic role mapping:

  1. Openthe bootstrap jazn.xml file, ORACLE_HOME/j2ee/instance/config/jazn.xml, in a text editor and go to the <jazn> element within the file.

  2. Search for a <property name="role.mapping.dynamic"> sub-element within the <jazn> element.

  3. If the sub-element exists, change the value to true or false; if the sub-element does not exist, create one. In either case, you should have a sub-element that looks like:

    <jazn provider="XML" location="./jazn-data.xml">
       <property name="role.mapping.dynamic" value="true" /> 
    </jazn>
    

    Note:

    Do not edit any <jazn> properties except as specified in this documentation.

  4. Restart OC4J.

Integrating Custom JAAS LoginModules

A custom JAAS LoginModule may be desirable when Oracle Identity Management is not available and users and roles are defined in an external repository. You can configure a LoginModule using the XML-based provider type. When you create a custom LoginModule, the following preliminary questions need to be considered.

  1. Development. Do you want to take advantage of J2EE security constraints?

  2. Development, packaging, and deployment. Are you using the login modules that come with J2SE 1.4? Or are you deploying custom or third-party login modules?


    Note:

    Custom login modules are supported only with the XML-based Provider.

Developing a LoginModule

You can use an any JAAS-compliant LoginModule within the OC4J framework. For general information on developing LoginModules, see the Sun JAAS documentation at http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html

When developing a LoginModule, you must consider several important issues:

Each of these is discussed in detail in its own section.

Subject-based Authorization

When you associate a custom LoginModule with an application, 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 LoginModule must add the relevant principals, including all roles and groups that the authenticated user participates in, to the Subject durring the commit phase of the JAAS authentication process.

J2EE Security Authorization

The OracleAS JAAS Provider custom LoginModule framework supports the J2EE declarative security model. This means that Subject-based authorization enforces the J2EE security constraints declared in an application's deployment descriptors (web.xml and ejb-jar.xml, for example). We encourage you to take advantage of the J2EE security model whenever possible.

Callback Support

The OracleAS JAAS Provider supports the standard javax.security.auth.callback name (NameCallback) and password (PasswordCallback) callbacks.

Debugging Tips

When debugging your secure application, bear the following issues in mind:

Debug Logging

If you set the JVM system property jazn.debug.log.enable to true, the OracleAS JAAS Provider logs debugging output to the console. Under Oracle Application Server, debugging output is captured in the directory ORACLE_HOME/opmn/logs.

Debugging LoginModules

We encourage you to include debugging options in your custom LoginModule. For an example, see the default login module, RealmLoginModule, which provides diagnostic output if debug is set to true.

Adding and Removing Login Modules

You use the JAZN Admintool to add and remove login modules. For basic information on running the JAZN Admintool, see "Admintool Overview" .

java -jar jazn.jar -addloginmodule application_name login_module_name    control_flag [optionname=value ...] 
 java -jar jazn.jar -remloginmodule application_name login_module_name 

The -addloginmodule option configures a new LoginModule for the named application.

The control_flag must be one of required, requisite, sufficient or optional, as specified in javax.security.auth.login.Configuration. See Table 10-1.

Table 10-1 LoginModule Control Flags

Flag Meaning
Required The LoginModule must succeed. Whether or not it succeeds, authentication proceeds down the LoginModule list.
Requisite The LoginModule must succeed. If it succeeds, authentication continues down the LoginModule list. If it fails, control immediately returns to the application (authentication does not continue down the LoginModule list).
Sufficient The LoginModule is not required to succeed. If it succeeds, control immediately returns to the application and authentication does not proceed down the LoginModule list. If it fails, authentication continues down the LoginModule list.
Optional The LoginModule is not required to succeed. Whether or not it succeeds, authentication proceeds down the LoginModule list.

If the LoginModule accepts its own options, you specify each option and its value as an optionname=value pair. Each LoginModule has its own individual set of options.

For instance, to add MyLoginModule to the application myapp as a required module with debug set to true, type:

java -jar jazn.jar -addloginmodule myapp MyLoginModule required debug=true

To delete MyLoginModule from myapp, type:

java -jar jazn.jar -remloginmodule myapp MyLoginModule

Admintool shell:

JAZN:> addloginmodule myapp MyLoginModule required debug=true 
JAZN: remloginmodule myapp MyLoginModule

Listing Login Modules

You use the JAZN Admintool to list login modules. For basic information on running the JAZN Admintool, see "Admintool Overview" .

java -jar jazn.jar -listloginmodules [application_name [login_module_class]]

The -listloginmodules option displays all LoginModules either in the specified application_name , or, if no application_name is specified, in all applications. Specifying login_module_class, after application_name displays information on only the specified class within the application.

For example, to display all LoginModules for the application myapp, type:

java -jar jazn.jar -listloginmodules myapp

Admintool shell:

JAZN:> listloginmodules myapp

Packaging and Deploying

If you are using one or more of the default login modules provided with J2SE 1.3 and 1.4 (such as the J2SE1.4 com.sun.security.auth.module.Krb5LoginModule), then no additional configuration is needed. The OracleAS JAAS Provider can locate the default login modules.

If you are deploying your application with a custom login module, then you must deploy the login module and configure the OracleAS JAAS Provider properly so that the module can be found at runtime.

The following options are available when packaging and deploying your custom login modules:

The remainder of this section discusses these options in greater detail.

Deploying as Standard Extensions or Optional Packages

If you deploy your login modules as standard extensions, the OracleAS JAAS Provider will be able to find them. No additional configuration is necessary. Deploying login modules as standard extensions allows multiple applications to share the deployed login modules.

For example, one way to deploy your login modules as standard extensions is to deploy them to the $J2EE_HOME/lib/ext directory.

Deploying Within the J2EE Application

If your login module is used only by a single J2EE application rather than shared among multiple applications, then you can simply package your login module as part of your application, and the OracleAS JAAS Provider will be able to find it. No additional configuration is necessary.

If a later application needs the same LoginModule, you must repackage the login module and any relevant classes with the new application.

If you want to enable multiple applications to share the same LoginModule but you cannot deploy the LoginModule as an extension, then you can consider using the OC4J classloading mechanism.

Using the OC4J Classloading Mechanism

The OracleAS JAAS Provider is integrated with OC4J's classloading architecture. If you configure your application so that the deployed custom login modules are part of your application classpath, then the OracleAS JAAS Provider can locate them.

One way to accomplish this is using the <library> element in either of the following files:

Configuring Your Application

You modify the following files to configure your application to take advantage of custom login modules:

This section gives details on the configuration files.


Note:

You must choose the XML-based provider when using custom login modules. See "Integrating Custom JAAS LoginModules".

jazn-data.xml

All login module configuration information is stored in the bootstrap jazn-data.xml file. This file is usually located in the directory ORACLE_HOME/j2ee/instance_name/config.


Note:

The bootstrap jazn-data.xml must contain accounts for "admin" and "anonymous". Do not remove these accounts; if you do, the administrative functions of the OracleAS JAAS Provider will not work.

Because the bootstrap jazn-data.xml file is instance-specific, you must modify it whenever you deploy your application into a new OC4J instance. You edit this file using the JAZN Admintool.

The following sections discuss these XML elements:

<jazn-loginconfig>

This tag contains information that associates applications with login modules.

Example 10-1 Example jazn-loginconfig element

<jazn-loginconfig>
  <application>
    <name>sampleLM</name>
    <login-modules>
       <login-module>
          <class>oracle.security.jazn.samples.SampleLoginModule</class>
          <control-flag>required</control-flag>
       </login-module>
    </login-modules>
  </application>
</jazn-loginconfig>

This fragment associates the application sampleLM with the login module sample.SampleLoginModule.


Note:

Do not remove login configuration information on RealmLoginModule.

<jazn-policy>

This tag contains information that associates grantees with permissions. If you want to make your fat client accessible to an EJB, you must explicitly make the permissions available. When you deploy a custom LoginModule in OC4J, you normally use custom principal classes or types. To grant or revoke permissions to these types, use the JAZN Admintool.

Example 10-2 Example jazn-policy element

<jazn-policy>
  <grant>
   <grantee>
     <principals>
      <principal>
        <class>oracle.security.jazn.samples.SampleUser</class>
        <name>admin</name>
      </principal>
    </principals>
   </grantee>
   <permissions>
     <permission>
       <class>com.evermind.server.rmi.RMIPermission</class>
       <name>login</name>
     </permission>
   </permissions>
  </grant>
</jazn-policy>

This fragment grants the permission com.evermind.server.rmi.RMIPermission with target name login to the principal with class oracle.security.jazn.samples.SampleUser and name admin.


Note:

Oracle recommends that you manage the contents of jazn-data.xml using the JAZN Admintool.

For more information about the JAZN Admintool, see Chapter 8, "Configuring the XML-Based Provider".

web.xml or ejb-jar.xml

To take advantage of J2EE declarative security in your application, you must configure the appropriate security constraints, either using your IDE or by hand-editing either web.xml or ejb-jar.xml. For details on these files, see the J2EE standard documentation at http://java.sun.com/j2ee.

orion-application.xml

This file is a container-specific deployment descriptor that is generated for each application deployed in OC4J. The following elements are relevant to writing custom LoginModules:


Note:

This section discusses only elements relevant to security. For a full discussion of this file, see the Oracle Application Server Containers for J2EE User's Guide.

<jazn>


Note:

For a discussion of how to locate the <jazn> element, see "Locating the <jazn> element".

The following <jazn> property is specific to LoginModule 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 the application specific jazn-data.xml.

    The LoginModule instance(s) must ensure that the appropriate principals (users, roles, or groups) 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.

<jazn provider="XML" location="./jazn-data.xml">
   <property name="role.mapping.dynamic" value="true" />
</jazn>


Note:

For full details on dynamic role mapping, see "Configuring Dynamic Role Mapping".

<security-role-mapping>

When you set J2EE security constraints in web.xml or ejb-jar.xml, you must configure security role mapping.The optional <security-role-mapping> element describes static security-role mapping information. If you set J2EE security constraints in your application's deployment descriptors (web.xml or ejb-jar.xml), you must configure security role mapping.

For details, see "Authenticating and Authorizing EJB Applications" .

<library>

This tag sets the classpath associated with your application. (nested in libraries) Example:

<library path="../../shared/lib/sample.jar"/>
<library path="../../shared/lib/samplemodule.jar"/>

oc4j-ra.xml (J2EE Connector Architecture only)

Each <connector-factory> element in oc4j-ra.xml 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.

  <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>

Simple Login Module J2EE Integration

Developing a simple LoginModule follows the standard development, packaging, and deployment cycle. The following sections discuss each step in the cycle.

Development

Develop a JAAS-compliant LoginModule according to the JAAS SPI (see the Javadoc for javax.security.auth.spi.LoginModule for more information).

Packaging

Package your LoginModule classes as part of your application's EAR file. For Web applications, include the classes under the WEB-INF/classes.

Deployment

To deploy your LoginModule in the bootstrap jazn-data.xml file:

  1. Register your application's login module within the <application> tag.

    The following entry registers the login module oracle.security.jazn.samples.SampleLoginModule to be used for authenticating users accessing the sampleLM application.

     <application>
             <name>sampleLM</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>
    
    
  2. Optional. Grant relevant permissions to your users and roles.

    For example, if the principal admin needs EJB access, then you must grant the permission com.evermind.rmi.RMIPermission to admin.

    <grant>
      <grantee>
        <principals>
          <principal>
            <class>oracle.security.jazn.samples.SampleUser</class>
            <name>admin</name>
          </principal>
        </principals>
      </grantee>
      <permissions>
        <permission>
          <class>com.evermind.server.rmi.RMIPermission</class>
          <name>login</name>
        </permission>
      </permissions>
    </grant>
    

To deploy your LoginModule in the application-specific orion-application.xml file:

  1. Set the <jazn> property role.mapping.dynamic to true:

    <jazn provider="XML" location="./jazn-data.xml" >
      <property name="role.mapping.dynamic" value="true" />
    </jazn>
    
  2. Create appropriate <security-role-mapping> entries.

    <security-role-mapping name="sr_developer">
      <user name="developer" />
    </security-role-mapping>
    <security-role-mapping name="sr_manager">
      <group name="managers" />
    </security-role-mapping>
    

Custom LoginModule Example

This section gives source code for a simple custom LoginModule to be used by the CallerInfo example; you can find the complete source code for the revised example by searching the Oracle Technology Network at http://www.oracle.com/technology/index.html.

Example 10-3 SampleLoginModule.java

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 <code>LoginModule</code>.
     * <p/>
     * <p/>
     *
     * @param subject         the <code>Subject</code> to be authenticated. <p>
     * @param callbackHandler a <code>CallbackHandler</code> for communicating
     *                        with the end user (prompting for usernames and
     *                        passwords, for example). <p>
     * @param sharedState     shared <code>LoginModule</code> state. <p>
     * @param options         options specified in the login
     *                        <code>Configuration</code> for this particular
     *                        <code>LoginModule</code>.
     */
    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.
     * <p/>
     * <p/>
     *
     * @return true if the authentication succeeded, or false if this
     *         <code>LoginModule</code> should be ignored.
     * @throws FailedLoginException if the authentication fails. <p>
     * @throws LoginException       if this <code>LoginModule</code>
     *                              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 
        // tag 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");
        }
 
 
        ((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; 
    }
 
 
    /**
     * <p> This method is called if the LoginContext's
     * overall authentication succeeded
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * succeeded).
     * <p/>
     * <p> If this LoginModule's own authentication attempt
     * succeeded (checked by retrieving the private state saved by the
     * <code>login</code> method), then this method associates a
     * <code>Principal</code>
     * with the <code>Subject</code> located in the
     * <code>LoginModule</code>.  If this LoginModule's own
     * authentication attempted failed, then this method removes
     * any state that was originally saved.
     * <p/>
     * <p/>
     *
     * @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());
        }
    }
 
 
    /**
     * <p> This method is called if the LoginContext's
     * overall authentication failed.
     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
     * did not succeed).
     * <p/>
     * <p> If this LoginModule's own authentication attempt
     * succeeded (checked by retrieving the private state saved by the
     * <code>login</code> and <code>commit</code> methods),
     * then this method cleans up any state that was originally saved.
     * <p/>
     * <p/>
     *
     * @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.
     * <p/>
     * <p> This method removes the <code>Principal</code>
     * that was added by the <code>commit</code> method.
     * <p/>
     * <p/>
     *
     * @return true in all cases since this <code>LoginModule</code>
     *         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) {
        }
    }
}

The Principal that this LoginModule uses is in Example 10-4.

Example 10-4 SamplePrincipal example

package oracle.security.jazn.samples;
 
import java.security.Principal;
 
class SamplePrincipal implements Principal {
 
    private String _name = null;
        
 
    SamplePrincipal(String name) {
        _name = name;
    }
 
    
    public boolean equals(Object another) {
        return ((SamplePrincipal)another).getName().equals(_name);
    }
 
 
    public String getName() {
        return _name;
    }
 
 
    public int hashCode() {
        return _name.hashCode();
    }
 
 
    public String toString() {
        return "[SamplePrincipal] : " + _name;
    }
 
}