187 lines
12 KiB
HTML
187 lines
12 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||
|
<html>
|
||
|
<head>
|
||
|
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||
|
<LINK rel="stylesheet" type="text/css" href="../../../rzahg/ic.css">
|
||
|
|
||
|
<title>Develop with JAAS to log in programmatically</title>
|
||
|
</head>
|
||
|
|
||
|
<BODY>
|
||
|
<!-- Java sync-link -->
|
||
|
<SCRIPT LANGUAGE="Javascript" SRC="../../../rzahg/synch.js" TYPE="text/javascript"></SCRIPT>
|
||
|
|
||
|
<h3><a name="secdjaas"></a>Develop with JAAS to log in programmatically</h3>
|
||
|
|
||
|
<p>Java Authentication and Authorization Service (JAAS) is a new feature in WebSphere Application Server - Express Version 5. JAAS represents the strategic APIs for authentication and replaces the CORBA programmatic login APIs of previous releases. Additionally, WebSphere Application Server - Express provides some extensions to JAAS.</p>
|
||
|
|
||
|
<p>If the application is using custom JAAS login configuration, please make sure that the custom JAAS login configuration is properly defined. See <a href="seccjaas.htm">Configure JAAS login configuration</a> for details.</p>
|
||
|
|
||
|
<p>Some of the JAAS APIs are protected by Java 2 Security permissions, if these APIs are used by application code, please make sure that these permissions are added to the application was.policy file. See <a href="seccj2wa.htm">The was.policy file</a> for more information. For more details of which APIs are protected by Java 2 Security permissions, please check the J2SDK, JAAS, and WebSphere Application Server - Express APIs javadoc. The following lists some of the APIs used in the sample code in this documentation and the Java 2 Security permissions required by these APIs:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>javax.security.auth.login.LoginContext constructors are protected by javax.security.auth.AuthPermission createLoginContext.</li>
|
||
|
<li>javax.security.auth.Subject.doAs() and com.ibm.websphere.security.auth.WSSubject.doAs() are protected by javax.security.auth.AuthPermission doAs.</li>
|
||
|
<li>javax.security.auth.Subject.doAsPrivileged() and com.ibm.websphere.security.auth.WSSubject.doAsPrivileged() are protected by javax.security.auth.AuthPermission doAsPrivileged.</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>WebSphere Application Server - Express provides these extensions to JAAS:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><p><strong>com.ibm.websphere.security.auth.WSSubject</strong>
|
||
|
<br>Due to a design oversight in the JAAS 1.0 specification, javax.security.auth.Subject.getSubject() does not return the Subject associated with the thread of execution inside a java.security.AccessController.doPrivileged() code block. This can present a inconsistent behavior that is problematic and causes undesireable effort. com.ibm.websphere.security.auth.WSSubject provides a workaround to associate Subject to thread of execution.</p> <p>com.ibm.websphere.security.auth.WSSubject extends the JAAS model to J2EE resources for authorization checks. If the Subject associates with the thread of execution within com.ibm.websphere.security.auth.WSSubject.doAs() or if the com.ibm.websphere.security.auth.WSSubject.doAsPrivileged() code block contains product credentials, the Subject will be used for J2EE resources authorization checks. For more information, see <a href="../program/apidocs/ae/com/ibm/websphere/security/auth/WSSubject.html">com.ibm.websphere.security.auth.WSSubject</a>. <img src="api.gif" width="18" height="15" align="absbottom" alt="Go to API documentation"></p></li>
|
||
|
|
||
|
|
||
|
<li><p><strong>WebSphere JAAS login configurations</strong>
|
||
|
<br>WebSphere provides a JAAS login configuration for applications to perform programmatic authentication to the WebSphere security runtime. This WebSphere JAAS login configuration performs authentication to the WebSphere configured authentication mechanism (SWAM or LTPA) and user registry (LocalOS, LDAP or Custom) based on the authentication data supplied. The authenticated Subject from this JAAS login configuration contains the required Principal and Credentials that can be used by WebSphere security runtime to perform authorization checks on J2EE role-based protected resources.</p>
|
||
|
|
||
|
<p>Here is the JAAS login configuration provided by WebSphere:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li><p><strong>WSLogin JAAS login configuration</strong>
|
||
|
<br>This is a generic JAAS login configuration that can be used by servlets and JSP components to perform authentication based on a user ID and password or on a token that is passed to the WebSphere security runtime.</p>
|
||
|
|
||
|
<p><strong>Note:</strong> A subject that is authenticated with the above JAAS login configuration contains a com.ibm.websphere.security.auth.WSPrincipal and a com.ibm.websphere.security.auth.WSCredential. If the authenticated Subject is passed in com.ibm.websphere.security.auth.WSSubject.doAs() (or the other doAs() methods), the WebSphere security runtime can perform authorization checks on J2EE resources based on the Subject com.ibm.websphere.security.auth.WSCredential.</p></li>
|
||
|
</ul></li>
|
||
|
|
||
|
<li><p><strong>User defined JAAS login configurations</strong>
|
||
|
<br>You can can define other JAAS login configurations. See <a href="seccjaas.htm">Configure Java Authentication and Authorization Service login</a> for details. Use these login configurations to perform programmatic authentication to your user defined authentication mechanism. However, the Subjects from these user defined JAAS login configurations might not be usable by WebSphere security runtime to perform authorization checks if they do not contain the required principal and credentials.</p></li>
|
||
|
</ul>
|
||
|
|
||
|
<p><strong>Version 5.0.1 and later:</strong></p>
|
||
|
<ul>
|
||
|
<li><p>The subject object generated by the WSLoginModuleImpl instance contains a principal that implements the WSPrincipal interface. Using the getCredential() method for a WSPrincipal object returns an object that implements the WSCredential interface. You can also find the WSCredential object instance in the PublicCredentials list of the subject instance. You should retrieve the WSCredential object from the PublicCredentials list instead of using the getCredential() method.</p></li>
|
||
|
<li><p>The getCallerPrincipal() method for the WSSubject class returns a string that represents the caller security identity.</p></li>
|
||
|
<li><p>The Subject object generated by the J2C DefaultPrincipalMapping module contains a resource principal and a PasswordCredentials list. The resource principal represents the caller.</p></li>
|
||
|
</ul>
|
||
|
|
||
|
<p>For programmatic login with JAAS, the product provides an implementation of the javax.security.auth.callback.CallbackHandler interface, which is called <a href=
|
||
|
"../program/apidocs/ae/com/ibm/websphere/security/auth/callback/WSCallbackHandlerImpl.html">com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl</a>. <img src="api.gif" width="18" height="15" align="absbottom" alt="Go to API documentation"> This com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl allows application to "push" authentication data to the WebSphere LoginModule to perform authentication. This can be useful for server side application code to authenticate an identity and use the identity to invoke downstream J2EE resources. Here is an example:</p>
|
||
|
|
||
|
<pre>javax.security.auth.login.LoginContext lc = null;
|
||
|
|
||
|
try {
|
||
|
lc = new javax.security.auth.login.LoginContext("WSLogin",
|
||
|
new com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl
|
||
|
("user", "securedpassword"));
|
||
|
|
||
|
// create a LoginContext and specify a CallbackHandler implementation
|
||
|
// CallbackHandler implementation determine how authentication data is collected
|
||
|
// in this case, the authentication data is "pushed" to the authentication
|
||
|
// mechanism implemented by the LoginModule.
|
||
|
} catch(javax.security.auth.login.LoginException e) {
|
||
|
System.err.println("ERROR: failed to instantiate a LoginContext "
|
||
|
+ "and the exception: " + e.getMessage());
|
||
|
e.printStackTrace();
|
||
|
|
||
|
// may be javax.security.auth.AuthPermission "createLoginContext" is not granted
|
||
|
// to the application, or the JAAS login configuration is not defined.
|
||
|
}
|
||
|
|
||
|
if (lc != null) {
|
||
|
try {
|
||
|
lc.login(); // perform login
|
||
|
|
||
|
// get the authenticated subject
|
||
|
javax.security.auth.Subject s = lc.getSubject();
|
||
|
|
||
|
// Invoke a J2EE resources using the authenticated subject
|
||
|
com.ibm.websphere.security.auth.WSSubject.doAs(s,
|
||
|
new java.security.PrivilegedAction() {
|
||
|
public Object run() {
|
||
|
try {
|
||
|
bankAccount.deposit(100.00);
|
||
|
// where bankAccount is an protected resource
|
||
|
} catch (Exception e) {
|
||
|
System.out.println("ERROR: error while accessing resource, exception: " +
|
||
|
e.getMessage());
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
) catch (javax.security.auth.login.LoginException e) {
|
||
|
System.err.println("ERROR: login failed with exception: " + e.getMessage());
|
||
|
e.printStackTrace();
|
||
|
|
||
|
// login failed, might want to provide relogin logic
|
||
|
}
|
||
|
}</pre>
|
||
|
|
||
|
<p>See <a href="secdjasx.htm">Example: JAAS programmatic login</a> for more information.</p>
|
||
|
|
||
|
<p><strong>Find the root cause login exception from a JAAS login (Version 5.0.2 and later)</strong></p>
|
||
|
|
||
|
<p>If you get a LoginException after issuing the LoginContext.login() API, you can find the root cause exception from the configured user registry. In the login modules, the registry exceptions are wrapped by a com.ibm.websphere.security.auth.WSLoginFailedException. This exception has a getCause() method that allows you to pull out the exception that was wrapped.</p>
|
||
|
|
||
|
<p><strong>Note:</strong> You are not always guaranteed to get an exception of type WSLoginFailedException, but you should note that most of the exceptions generated from the user registry show up here.</p>
|
||
|
|
||
|
<p>The following is a LoginContext.login() API example with associated catch block. WSLoginFailedException has to be casted to com.ibm.websphere.security.auth.WSLoginFailedException if you want to issue the getCause() API.</p>
|
||
|
|
||
|
<p><strong>Note:</strong> The determineCause() example below can be used for processing CustomUserRegistry exception types.</p>
|
||
|
|
||
|
<pre>try {
|
||
|
lc.login();
|
||
|
} catch (LoginException le) {
|
||
|
// Drill down through the exceptions as they might cascade through the runtime.
|
||
|
Throwable root_exception = determineCause(le);
|
||
|
|
||
|
// Now you can use "root_exception" to compare to a particular exception type.
|
||
|
// For example, if you have implemented a CustomUserRegistry type, you would know
|
||
|
// what to look for here.
|
||
|
}
|
||
|
|
||
|
/* Method used to drill down into the WSLoginFailedException to find the
|
||
|
* "root cause" exception */
|
||
|
public Throwable determineCause(Throwable e) {
|
||
|
Throwable root_exception = e, temp_exception = null;
|
||
|
|
||
|
// Keep looping until there are no more embedded WSLoginFailedException
|
||
|
// or WSSecurityException exceptions.
|
||
|
while (true) {
|
||
|
if (e instanceof com.ibm.websphere.security.auth.WSLoginFailedException) {
|
||
|
temp_exception =
|
||
|
((com.ibm.websphere.security.auth.WSLoginFailedException) e).getCause();
|
||
|
}
|
||
|
else if (e instanceof com.ibm.websphere.security.WSSecurityException) {
|
||
|
temp_exception =
|
||
|
((com.ibm.websphere.security.WSSecurityException) e).getCause();
|
||
|
}
|
||
|
else if (e instanceof com.ibm.ws.security.registry.os400.OS400RegistryException) {
|
||
|
// get OS400 specific error code, if configured
|
||
|
System.out.println ("Error code from OS400 exception: "
|
||
|
+ ((com.ibm.ws.security.registry.os400.OS400RegistryException)e).getErrorCode());
|
||
|
return e;
|
||
|
}
|
||
|
else if (e instanceof javax.naming.NamingException) {
|
||
|
// check for Ldap embedded exception
|
||
|
temp_exception = ((javax.naming.NamingException)e).getRootCause();
|
||
|
}
|
||
|
else if (e instanceof your_custom_exception_here) {
|
||
|
// your custom processing here, if necessary
|
||
|
}
|
||
|
else {
|
||
|
// This exception is not one of the types we are looking for, return now.
|
||
|
// This is the root from the WebSphere perspective
|
||
|
return root_exception;
|
||
|
}
|
||
|
|
||
|
if (temp_exception != null) {
|
||
|
// We have an exception, let's go back and see if this has another
|
||
|
// one embedded within it.
|
||
|
root_exception = temp_exception;
|
||
|
e = temp_exception;
|
||
|
continue;
|
||
|
}
|
||
|
else {
|
||
|
// We finally have the root exception from this call path,
|
||
|
// this has to occur at some point.
|
||
|
return root_exception;
|
||
|
}
|
||
|
}
|
||
|
}</pre>
|
||
|
|
||
|
</body>
|
||
|
</html>
|
||
|
|