See the WebSphere eXtreme Scale Wiki for links to eXtreme Scale Version 7.0 documentation.
If you log in
with your developerWorks ID, you can leave comments and feedback for the development team.
Previous step
This topic builds upon J2SE security tutorial step 1 - unsecured sample and adds client authentication to the previously unsecured application.
With client authentication enabled, a client is authenticated before connecting to the ObjectGrid server. This section demonstrates how client authentication can be done in an ObjectGrid server environment, including sample code and scripts to demonstrate. You can download the code from sample
.
As any other authentication mechanism, the minimum authentication consists of the following steps:
- The administrator changes configurations to make authentication a requirement.
- The client provides a credential to the server.
- The server authenticates the credential to the registry.
Client credential
A client credential is represented by a com.ibm.websphere.objectgrid.security.plugins.Credential interface. A client credential can be a user name and password pair, a Kerberos ticket, a client certificate, or data in any format that the client and server agree upon. Refer to Credential API Documentation
for more details.
This interface explicitly defines the equals(Object) and hashCode() methods. These two methods are important because the authenticated Subject objects are cached by using the Credential object as the key on the server side.
ObjectGrid also provides a plug-in to generate a credential. This plug-in is represented by the com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator interface, and is used to generate a client credential. This is useful when the credential is expirable. In this case, the getCredential() method is called to renew a credential. Refer to CredentialGenerator API Documentation
for more details.
You can implement these two interfaces for ObjectGrid client runtime to obtain client credentials.
To enhance the unsecured sample by adding the authentication feature, use a simple user password credential and credential generator. The user password credential generator stores a user ID and password. The user password credential generator then contains this user ID and password. For testing purposes, ObjectGrid provides these two plug-in implementations:
- com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredential
- com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredentialGenerator
The following example illustrates the Java code of these two classes to provide an idea of how to implement these two plug-ins:
package com.ibm.websphere.objectgrid.security.plugins.builtins;
import com.ibm.websphere.objectgrid.security.plugins.Credential;
/**
* This class represents a credential containing a user ID and password.
*
* @ibm-api
* @since WAS XD 6.0.1
*
* @see Credential
* @see UserPasswordCredentialGenerator#getCredential()
*/
public class UserPasswordCredential implements Credential {
private static final long serialVersionUID = 1409044825541007228L;
private String ivUserName;
private String ivPassword;
/**
* Creates a UserPasswordCredential with the specified user name and
* password.
*
* @param userName the user name for this credential
* @param password the password for this credential
*
* @throws IllegalArgumentException if userName or password is <code>null</code>
*/
public UserPasswordCredential(String userName, String password) {
super();
if (userName == null || password == null) {
throw new IllegalArgumentException("User name and password cannot be null.");
}
this.ivUserName = userName;
this.ivPassword = password;
}
/**
* Gets the user name for this credential.
*
* @return the user name argument that was passed to the constructor
* or the <code>setUserName(String)</code>
* method of this class
*
* @see #setUserName(String)
*/
public String getUserName() {
return ivUserName;
}
/**
* Sets the user name for this credential.
*
* @param userName the user name to set.
*
* @throws IllegalArgumentException if userName is <code>null</code>
*/
public void setUserName(String userName) {
if (userName == null) {
throw new IllegalArgumentException("User name cannot be null.");
}
this.ivUserName = userName;
}
/**
* Gets the password for this credential.
*
* @return the password argument that was passed to the constructor
* or the <code>setPassword(String)</code>
* method of this class
*
* @see #setPassword(String)
*/
public String getPassword() {
return ivPassword;
}
/**
* Sets the password for this credential.
*
* @param password the password to set.
*
* @throws IllegalArgumentException if password is <code>null</code>
*/
public void setPassword(String password) {
if (password == null) {
throw new IllegalArgumentException("Password cannot be null.");
}
this.ivPassword = password;
}
/**
* Checks two UserPasswordCredential objects for equality.
* <p>
* Two UserPasswordCredential objects are equal if and only if their user names
* and passwords are equal.
*
* @param o the object we are testing for equality with this object.
*
* @return <code>true</code> if both UserPasswordCredential objects are equivalent.
*
* @see Credential#equals(Object)
*/
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof UserPasswordCredential) {
UserPasswordCredential other = (UserPasswordCredential) o;
return other.ivPassword.equals(ivPassword) && other.ivUserName.equals(ivUserName);
}
return false;
}
/**
* Returns the hashcode of the UserPasswordCredential object.
*
* @return the hash code of this object
*
* @see Credential#hashCode()
*/
public int hashCode() {
return ivUserName.hashCode() + ivPassword.hashCode();
}
}
package com.ibm.websphere.objectgrid.security.plugins.builtins;
import java.util.StringTokenizer;
import com.ibm.websphere.objectgrid.security.plugins.Credential;
import com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator;
/**
* This credential generator creates <code>UserPasswordCredential</code> objects.
* <p>
* UserPasswordCredentialGenerator has a one to one relationship with
* UserPasswordCredential because it can only create a UserPasswordCredential
* representing one identity.
*
* @since WAS XD 6.0.1
* @ibm-api
*
* @see CredentialGenerator
* @see UserPasswordCredential
*/
public class UserPasswordCredentialGenerator implements CredentialGenerator {
private String ivUser;
private String ivPwd;
/**
* Creates a UserPasswordCredentialGenerator with no user name or password.
*
* @see #setProperties(String)
*/
public UserPasswordCredentialGenerator() {
super();
}
/**
* Creates a UserPasswordCredentialGenerator with a specified user name and
* password
*
* @param user the user name
* @param pwd the password
*/
public UserPasswordCredentialGenerator(String user, String pwd) {
ivUser = user;
ivPwd = pwd;
}
/**
* Creates a new <code>UserPasswordCredential</code> object using this
* object's user name and password.
*
* @return a new <code>UserPasswordCredential</code> instance
*
* @see CredentialGenerator#getCredential()
* @see UserPasswordCredential
*/
public Credential getCredential() {
return new UserPasswordCredential(ivUser, ivPwd);
}
/**
* Gets the password for this credential generator.
*
* @return the password argument that was passed to the constructor
*/
public String getPassword() {
return ivPwd;
}
/**
* Gets the user name for this credential.
*
* @return the user argument that was passed to the constructor
* of this class
*/
public String getUserName() {
return ivUser;
}
/**
* Sets additional properties namely a user name and password.
*
* @param properties a properties string with a user name and
* a password separated by a blank.
*
* @throws IllegalArgumentException if the format is not valid
*/
public void setProperties(String properties) {
StringTokenizer token = new StringTokenizer(properties, " ");
if (token.countTokens() != 2) {
throw new IllegalArgumentException(
"The properties should have a user name and password and separated by a blank.");
}
ivUser = token.nextToken();
ivPwd = token.nextToken();
}
/**
* Checks two UserPasswordCredentialGenerator objects for equality.
* <p>
* Two UserPasswordCredentialGenerator objects are equal if and only if
* their user names and passwords are equal.
*
* @param obj the object we are testing for equality with this object.
*
* @return <code>true</code> if both UserPasswordCredentialGenerator objects
* are equivalent.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj != null && obj instanceof UserPasswordCredentialGenerator) {
UserPasswordCredentialGenerator other = (UserPasswordCredentialGenerator) obj;
boolean bothUserNull = false;
boolean bothPwdNull = false;
if (ivUser == null) {
if (other.ivUser == null) {
bothUserNull = true;
} else {
return false;
}
}
if (ivPwd == null) {
if (other.ivPwd == null) {
bothPwdNull = true;
} else {
return false;
}
}
return (bothUserNull || ivUser.equals(other.ivUser)) && (bothPwdNull || ivPwd.equals(other.ivPwd));
}
return false;
}
/**
* Returns the hashcode of the UserPasswordCredentialGenerator object.
*
* @return the hash code of this object
*/
public int hashCode() {
return ivUser.hashCode() + ivPwd.hashCode();
}
}
So the UserPasswordCredential class contains two attributes: user name and password. The UserPasswordCredentialGenerator simply serves as a factory that contains the UserPasswordCredential objects.
Server authenticator
After the ObjectGrid client retrieves the Credential object using the CredentialGenerator object, this client Credential object is sent along with the client request to the ObjectGrid server. The ObjectGrid server authenticates the Credential object before processing the request. If the Credential object is authenticated successfully, a Subject object is returned to represent this client.
This Subject object is then cached, and it expires after its lifetime reaches the session timeout value. The login session timeout value can be set by using the loginSessionExpirationTime property in the cluster XML file. For example, setting loginSessionExpirationTime=″300″ makes the Subject object expire in 300 seconds.
This Subject object is then used for authorizing the request, which is shown later.
An ObjectGrid server uses the Authenticator plug-in to authenticate the Credential object. Refer to Authenticator API Documentation
for more details.
The Authenticator plug-in is where the ObjectGrid runtime authenticates the Credential object from the client user registry, for example, a Lightweight Directory Access Protocol (LDAP) server.
ObjectGrid does not provide an immediately available user registry configuration. The configuration and management of user registry is left outside of ObjectGrid for simplification and flexibility purposes. This plug-in implements connecting and authenticating to the user registry. For example, an Authenticator implementation extracts the user ID and password from the credential, uses them to connect and validate to an LDAP server, and creates a Subject object as a result of the authentication. The implementation could utilize JAAS login modules. A Subject object is returned as a result of authentication.
This example uses an ObjectGrid built-in implementation: KeyStoreLoginAuthenticator, which is for testing and sample purposes (a key store is a simple user registry and should not be used for production). Again, the class is displayed to further demonstrate how to implement an Authenticator.
package com.ibm.websphere.objectgrid.security.plugins.builtins;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import com.ibm.websphere.objectgrid.security.plugins.Authenticator;
import com.ibm.websphere.objectgrid.security.plugins.Credential;
import com.ibm.websphere.objectgrid.security.plugins.ExpiredCredentialException;
import com.ibm.websphere.objectgrid.security.plugins.InvalidCredentialException;
import com.ibm.ws.objectgrid.Constants;
import com.ibm.ws.objectgrid.ObjectGridManagerImpl;
import com.ibm.ws.objectgrid.security.auth.callback.UserPasswordCallbackHandlerImpl;
/**
* This class is an implementation of the <code>Authenticator</code> interface
* when a user name and password are used as a credential.
* <p>
* When user ID and password authentication is used, the credential passed to the
* <code>authenticate(Credential)</code> method is a UserPasswordCredential object.
* <p>
* This implementation will use a <code>KeyStoreLoginModule</code> to authenticate
* the user into the key store using the JAAS login module "KeyStoreLogin". The key
* store can be configured as an option to the <code>KeyStoreLoginModule</code>
* class. Please see the <code>KeyStoreLoginModule</code> class for more details
* about how to set up the JAAS login configuration file.
* <p>
* This class is only for sample and quick testing purpose. Users should
* write your own Authenticator implementation which can fit better into
* the environment.
*
* @ibm-api
* @since WAS XD 6.0.1
*
* @see Authenticator
* @see KeyStoreLoginModule
* @see UserPasswordCredential
*/
public class KeyStoreLoginAuthenticator implements Authenticator {
/**
* Creates a new KeyStoreLoginAuthenticator.
*/
public KeyStoreLoginAuthenticator() {
super();
}
/**
* Authenticates a <code>UserPasswordCredential</code>.
* <p>
* Uses the user name and password from the specified UserPasswordCredential
* to login to the KeyStoreLoginModule named "KeyStoreLogin".
*
* @throws InvalidCredentialException if credential isn't a
* UserPasswordCredential or some error occurs during processing
* of the supplied UserPasswordCredential
*
* @throws ExpiredCredentialException if credential is expired. This exception
* is not used by this implementation
*
* @see Authenticator#authenticate(Credential)
* @see KeyStoreLoginModule
*/
public Subject authenticate(Credential credential) throws InvalidCredentialException, ExpiredCredentialException {
if (credential == null) {
throw new InvalidCredentialException("Supplied credential is null");
}
if (! (credential instanceof UserPasswordCredential) ) {
throw new InvalidCredentialException("Supplied credential is not a UserPasswordCredential");
}
UserPasswordCredential cred = (UserPasswordCredential) credential;
LoginContext lc = null;
try {
lc = new LoginContext("KeyStoreLogin",
new UserPasswordCallbackHandlerImpl(cred.getUserName(), cred.getPassword().toCharArray()));
lc.login();
Subject subject = lc.getSubject();
return subject;
}
catch (LoginException le) {
throw new InvalidCredentialException(le);
}
catch (IllegalArgumentException ile) {
throw new InvalidCredentialException(ile);
}
}
}
package com.ibm.websphere.objectgrid.security.plugins.builtins;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.security.auth.x500.X500Principal;
import javax.security.auth.x500.X500PrivateCredential;
import com.ibm.websphere.objectgrid.ObjectGridRuntimeException;
import com.ibm.ws.objectgrid.Constants;
import com.ibm.ws.objectgrid.ObjectGridManagerImpl;
import com.ibm.ws.objectgrid.util.ObjectGridUtil;
/**
* A KeyStoreLoginModule is keystore authentication login module based on
* JAAS authentication.
* <p>
* A login configuration should provide an option "<code>keyStoreFile</code>" to
* indicate where the keystore file is located. If the <code>keyStoreFile</code>
* value contains a system property in the form, <code>${system.property}</code>,
* it will be expanded to the value of the system property.
* <p>
* If an option "<code>keyStoreFile</code>" is not provided, the default keystore
* file name is <code>"${java.home}${/}.keystore"</code>.
* <p>
* Here is a Login module configuration example:
* <pre><code>
* KeyStoreLogin {
* com.ibm.websphere.objectgrid.security.plugins.builtins.KeystoreLoginModule required
* keyStoreFile="${user.dir}${/}security${/}.keystore";
* };
* </code></pre>
*
* @ibm-api
* @since WAS XD 6.0.1
*
* @see LoginModule
*/
public class KeyStoreLoginModule implements LoginModule {
private static final String CLASS_NAME = KeyStoreLoginModule.class.getName();
/**
* Key store file property name
*/
public static final String KEY_STORE_FILE_PROPERTY_NAME = "keyStoreFile";
/**
* Key store type. Only JKS is supported
*/
public static final String KEYSTORE_TYPE = "JKS";
/**
* The default key store file name
*/
public static final String DEFAULT_KEY_STORE_FILE = "${java.home}${/}.keystore";
private CallbackHandler handler;
private Subject subject;
private boolean debug = false;
private Set principals = new HashSet();
private Set publicCreds = new HashSet();
private Set privateCreds = new HashSet();
protected KeyStore keyStore;
/**
* Creates a new KeyStoreLoginModule.
*/
public KeyStoreLoginModule() {
}
/**
* Initializes the login module.
*
* @see LoginModule#initialize(Subject, CallbackHandler, Map, Map)
*/
public void initialize(Subject sub, CallbackHandler callbackHandler,
Map mapSharedState, Map mapOptions) {
debug = "true".equalsIgnoreCase((String) mapOptions.get("debug"));
if (sub == null)
throw new IllegalArgumentException("Subject is not specified");
if (callbackHandler == null)
throw new IllegalArgumentException(
"CallbackHander is not specified");
String sKeyStorePath = (String) mapOptions
.get(KEY_STORE_FILE_PROPERTY_NAME);
if (sKeyStorePath == null) {
sKeyStorePath = DEFAULT_KEY_STORE_FILE;
}
sKeyStorePath = ObjectGridUtil.replaceVar(sKeyStorePath);
File fileKeyStore = new File(sKeyStorePath);
try {
KeyStore store = KeyStore.getInstance("JKS");
store.load(new FileInputStream(fileKeyStore), null);
keyStore = store;
if (debug) {
System.out.println("[KeyStoreLoginModule] initialize: Successfully loaded key store");
}
}
catch (Exception e) {
ObjectGridRuntimeException re = new ObjectGridRuntimeException(
"Failed to load keystore: " + fileKeyStore.getAbsolutePath());
re.initCause(e);
if (debug) {
System.out.println("[KeyStoreLoginModule] initialize: Key store loading failed with exception "
+ e.getMessage());
}
}
this.subject = sub;
this.handler = callbackHandler;
}
/**
* Authenticates a user based on the keystore file.
*
* @see LoginModule#login()
*/
public boolean login() throws LoginException {
if (debug) {
System.out.println("[KeyStoreLoginModule] login: entry");
}
String name = null;
char pwd[] = null;
if (keyStore == null || subject == null || handler == null) {
throw new LoginException("Module initialization failed");
}
NameCallback nameCallback = new NameCallback("Username:");
PasswordCallback pwdCallback = new PasswordCallback("Password:", false);
try {
handler.handle(new Callback[] { nameCallback, pwdCallback });
}
catch (Exception e) {
throw new LoginException("Callback failed: " + e);
}
name = nameCallback.getName();
char[] tempPwd = pwdCallback.getPassword();
if (tempPwd == null) {
tempPwd = new char[0];
}
pwd = new char[tempPwd.length];
System.arraycopy(tempPwd, 0, pwd, 0, tempPwd.length);
pwdCallback.clearPassword();
if (debug) {
System.out.println("[KeyStoreLoginModule] login: "
+ "user entered user name: " + name);
}
try {
validate(name, pwd);
}
catch (SecurityException se) {
principals.clear();
publicCreds.clear();
privateCreds.clear();
LoginException le = new LoginException(
"Exception encountered during login");
le.initCause(se);
throw le;
}
if (debug) {
System.out.println("[KeyStoreLoginModule] login: exit");
}
return true;
}
/**
* Indicates the user is accepted.
* <p>
* This method is called only if the user is authenticated by all modules in
* the login configuration file. The principal objects will be added to the
* stored subject.
*
* @return false if for some reason the principals cannot be added; true
* otherwise
*
* @exception LoginException
* LoginException is thrown if the subject is readonly or if
* any unrecoverable exceptions is encountered.
*
* @see LoginModule#commit()
*/
public boolean commit() throws LoginException {
if (debug) {
System.out.println("[KeyStoreLoginModule] commit: entry");
}
if (principals.isEmpty()) {
throw new IllegalStateException("Commit is called out of sequence");
}
if (subject.isReadOnly()) {
throw new LoginException("Subject is Readonly");
}
subject.getPrincipals().addAll(principals);
subject.getPublicCredentials().addAll(publicCreds);
subject.getPrivateCredentials().addAll(privateCreds);
principals.clear();
publicCreds.clear();
privateCreds.clear();
if (debug) {
System.out.println("[KeyStoreLoginModule] commit: exit");
}
return true;
}
/**
* Indicates the user is not accepted
*
* @see LoginModule#abort()
*/
public boolean abort() throws LoginException {
boolean b = logout();
return b;
}
/**
* Logs the user out. Clear all the maps.
*
* @see LoginModule#logout()
*/
public boolean logout() throws LoginException {
principals.clear();
publicCreds.clear();
privateCreds.clear();
if (!subject.isReadOnly()) {
if (subject.getPrincipals() != null) {
subject.getPrincipals().clear();
}
if (subject.getPublicCredentials() != null) {
subject.getPublicCredentials().clear();
}
if (subject.getPrivateCredentials() != null) {
subject.getPrivateCredentials().clear();
}
}
return true;
}
/**
* Validates the user name and password based on the keystore.
*
* @param userName user name
* @param password password
* @throws SecurityException if any exceptions encountered
*/
private void validate(String userName, char password[])
throws SecurityException {
PrivateKey privateKey = null;
try {
privateKey = (PrivateKey) keyStore.getKey(userName, password);
}
catch (NoSuchAlgorithmException nsae) {
SecurityException se = new SecurityException();
se.initCause(nsae);
throw se;
}
catch (KeyStoreException kse) {
SecurityException se = new SecurityException();
se.initCause(kse);
throw se;
}
catch (UnrecoverableKeyException uke) {
SecurityException se = new SecurityException();
se.initCause(uke);
throw se;
}
if (privateKey == null) {
throw new SecurityException("Invalid name: " + userName);
}
Certificate certs[] = null;
try {
certs = keyStore.getCertificateChain(userName);
}
catch (KeyStoreException kse) {
SecurityException se = new SecurityException();
se.initCause(kse);
throw se;
}
if (debug) {
System.out.println(" Print out the certificates:");
for (int i = 0; i < certs.length; i++) {
System.out.println(" certificate " + i);
System.out.println(" " + certs[i]);
}
}
if (certs != null && certs.length > 0) {
if (certs[0] instanceof X509Certificate) {
try {
X509Certificate certX509 = (X509Certificate) certs[0];
X500Principal principal = new X500Principal(certX509
.getIssuerDN()
.getName());
principals.add(principal);
if (debug) {
System.out.println(" Principal added: " + principal);
}
CertificateFactory factory = CertificateFactory
.getInstance("X.509");
java.security.cert.CertPath certPath = factory
.generateCertPath(Arrays.asList(certs));
publicCreds.add(certPath);
privateCreds.add(new X500PrivateCredential(certX509,
privateKey, userName));
}
catch (CertificateException ce) {
SecurityException se = new SecurityException();
se.initCause(ce);
throw se;
}
}
else {
publicCreds.add(certs[0]);
privateCreds.add(privateKey);
}
}
}
}
This KeyStoreLoginAuthenticator uses a KeyStoreLoginModule to authenticate the user with the key store by using the JAAS login module "KeyStoreLogin". The key store can be configured as an option to the KeyStoreLoginModule class. The following example illustrates the keyStoreLogin alias configured in the JAAS configuration file og_jaas.config:
KeyStoreLogin{
com.ibm.websphere.objectgrid.security.plugins.builtins.KeyStoreLoginModule required
keyStoreFile="../security/sampleKS.jks" debug = true;
};
The following commands create a key store sampleKS.jks in the %OBJECTGRID_HOME%/security directory with the password as sampleKS1. Also, three user certificates representing the administrator user, the manager user, and the cashier user are created with their own passwords.
- cd objectgridRoot
- mkdir security
- cd security
- keytool -genkey -v -keystore ./sampleKS.jks -storepass sampleKS1 -alias administrator -keypass administrator1 -dname CN=administrator,O=acme,OU=OGSample -validity 10000
- keytool -genkey -v -keystore ./sampleKS.jks -storepass sampleKS1 -alias manager -keypass manager1 -dname CN=manager,O=acme,OU=OGSample -validity 10000
- keytool -genkey -v -keystore ./sampleKS.jks -storepass sampleKS1 -alias cashier -keypass cashier1 -dname CN=cashier,O=acme,OU=OGSample -validity 10000
The client security configuration is configured in the security.ogclient.props file. Use the following command to create a copy in the %OBJECTGRID_HOME%/security directory:
- cd objectgridRoot/security
- cp ../properties/security.ogclient.props
The default security.ogclient.props should work. The following properties are highlighted in the security.ogclient.props file in security directory:
- securityEnabled: Setting securityEnabled to true (defalt value) enables the client security, which includes authentication.
- credentialAuthentication: Set credentialAuthentication to Supported (default value), which means the client supports credential authentication.
- transportType: Set transportType to TCP/IP, which means no SSL will be used.
- singleSignOnEnabled: Set it to false (default value). Single sign-on is not available.
Server security configuration
The server security configuration is specified in the security descriptor XML file and the server security property file.
The security descriptor XML file describes the security properties common to all servers (including catalog servers and container servers). One property example is the authenticator configuration which represents the user registry and authentication mechanism.
Here is the security.xml to be used in this sample:
<?xml version="1.0" encoding="UTF-8"?>
<securityConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ibm.com/ws/objectgrid/config/security ../objectGridSecurity.xsd"
xmlns="http://ibm.com/ws/objectgrid/config/security">
<security securityEnabled="true" loginSessionExpirationTime="300" >
<authenticator className ="com.ibm.websphere.objectgrid.security.plugins.builtins.KeyStoreLoginAuthenticator">
</authenticator>
</security>
</securityConfig>
- securityEnabled: Setting securityEnabled to true enables the server security, which includes authentication.
- loginSessionExpirationTime: Set the value to 300 (default value).
- authenticator: Add the authenticator class KeyStoreLoginAuthenticator to the cluster XML file as follows:
<authenticator className ="com.ibm.websphere.objectgrid.security.plugins.builtins.KeyStoreLoginAuthenticator">
</authenticator>
For more detailed explanation on security.xml, refer to Configuring for deployment with security XML.
Copy the security.ogserver.props into the security directory. At this time, you do not need to modify anything in this file.
- cd objectgridRoot/security
- cp ../properties/containerServer.properties server.props
Complete the following changes in the server.props file:
- securityEnabled: Set securityEnabled to true.
- transportType: Set transportType to TCP/IP, which means no SSL will be used.
- secureTokenManagerType: Set secureTokenManagerType to none to not configure the secure token manager.
Secure client
Connect the client application to the server securely as demonstrated in the following example:
package com.ibm.websphere.objectgrid.security.sample.guide;
import com.ibm.websphere.objectgrid.ClientClusterContext;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.security.config.ClientSecurityConfiguration;
import com.ibm.websphere.objectgrid.security.config.ClientSecurityConfigurationFactory;
import com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator;
import com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredentialGenerator;
public class SecureSimpleApp extends SimpleApp {
public static void main(String[] args) throws Exception {
SecureSimpleApp app = new SecureSimpleApp();
app.run(args);
}
/**
* Get the ObjectGrid
* @return an ObjectGrid instance
* @throws Exception
*/
protected ObjectGrid getObjectGrid(String[] args) throws Exception {
ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ogManager.setTraceFileName("logs/client.log");
ogManager.setTraceSpecification("ObjectGrid*=all=enabled:ORBRas=all=enabled");
ClientSecurityConfiguration clientSC = ClientSecurityConfigurationFactory
.getClientSecurityConfiguration(args[0]);
CredentialGenerator credGen = new UserPasswordCredentialGenerator(args[1], args[2]);
clientSC.setCredentialGenerator(credGen);
ClientClusterContext ccContext = ogManager.connect("localhost:2809", clientSC, null);
ObjectGrid og = ogManager.getObjectGrid(ccContext, "accounting");
return og;
}
}
There are three things different from the non-secured application:
- Created a ClientSecurityConfiguration object by passing the configured security.ogclient.props file.
- Created a UserPasswordCredentialGenerator by using the passed-in user ID and password.
- Connected to the catalog server to obtain ObjectGrid from the ClientClusterContext.
Issue the application
To run the application, start the catalog server. Issue the -clusterFile and -serverSecurityFile to pass in the security properties:
- cd objectgridRoot/bin
startOgServer.sh catalogServer -clusterSecurityFile ../security/security.xml -serverProps ../security/server.props -jvmArgs -Djava.security.auth.login.config="../security/og_jaas.config"
startOgServer.bat catalogServer -clusterSecurityFile ../security/security.xml -serverProps ../security/server.props -jvmArgs -Djava.security.auth.login.config="../security/og_jaas.config"
Then, launch a secure container server by using the following script:
- cd objectgridRoot/bin
startOgServer.sh c0 -objectgridFile ../xml/SimpleApp.xml -deploymentPolicyFile ../xml/SimpleDP.xml -catalogServiceEndpoints localhost:2809 -serverProps ../security/server.props -jvmArgs -Djava.security.auth.login.config="../security/og_jaas.config"
startOgServer.bat c0 -objectgridFile ../xml/SimpleApp.xml -deploymentPolicyFile ../xml/SimpleDP.xml -catalogServiceEndpoints localhost:2809 -serverProps ../security/server.props -jvmArgs -Djava.security.auth.login.config="../security/og_jaas.config"
The server property file is passed by issuing -serverProps. You can refer to Starting ObjectGrid server processes to read more about launching container servers. Refer to the server property file template for details.
After the server is started, launch the client by using the following command:
- cd objectgridRoot/bin
- java -classpath ../lib/objectgrid.jar;../applib/secsample.jar com.ibm.websphere.objectgrid.security.sample.guide.SecureSimpleApp ../security/security.ogclient.props manager manager1
The secsample.jar file contains the SimpleApp class.
The SecureSimpleApp uses three parameters that are provided in the following list:
- The ../security/security.ogclient.props file is the client security property file.
- manager is the user ID.
- manager1 is the password.
After you issue the class, you will see the following output:
The customer name for ID 0001 is fName lName.
Now, you have successfully made your system partially secure by enabling authentication. You configured the server to plug in the user registry, configured the client to provide client credentials, and changed the client property file and cluster XML file to enable authentication.
If you provide an invalidate password, you see an exception stating that the user name or password is not correct.
For more details about client authentication, please refer to Client authentication reference.
Next step
Additional information
© Copyright IBM Corporation 2007,2009. All Rights Reserved.