/** * <p> A <code>Subject</code> represents a grouping of related information * for a single entity, such as a person. * Such information includes the Subject's identities as well as * its security-related attributes * (passwords and cryptographic keys, for example). * * <p> Subjects may potentially have multiple identities. * Each identity is represented as a <code>Principal</code> * within the <code>Subject</code>. Principals simply bind names to a * <code>Subject</code>. For example, a <code>Subject</code> that happens * to be a person, Alice, might have two Principals: * one which binds "Alice Bar", the name on her driver license, * to the <code>Subject</code>, and another which binds, * "999-99-9999", the number on her student identification card, * to the <code>Subject</code>. Both Principals refer to the same * <code>Subject</code> even though each has a different name. * * <p> A <code>Subject</code> may also own security-related attributes, * which are referred to as credentials. * Sensitive credentials that require special protection, such as * private cryptographic keys, are stored within a private credential * <code>Set</code>. Credentials intended to be shared, such as * public key certificates or Kerberos server tickets are stored * within a public credential <code>Set</code>. Different permissions * are required to access and modify the different credential Sets. * * <p> To retrieve all the Principals associated with a <code>Subject</code>, * invoke the <code>getPrincipals</code> method. To retrieve * all the public or private credentials belonging to a <code>Subject</code>, * invoke the <code>getPublicCredentials</code> method or * <code>getPrivateCredentials</code> method, respectively. * To modify the returned <code>Set</code> of Principals and credentials, * use the methods defined in the <code>Set</code> class. * For example: * <pre> * Subject subject; * Principal principal; * Object credential; * * // add a Principal and credential to the Subject * subject.getPrincipals().add(principal); * subject.getPublicCredentials().add(credential); * </pre> * * <p> This <code>Subject</code> class implements <code>Serializable</code>. * While the Principals associated with the <code>Subject</code> are serialized, * the credentials associated with the <code>Subject</code> are not. * Note that the <code>java.security.Principal</code> class * does not implement <code>Serializable</code>. Therefore all concrete * <code>Principal</code> implementations associated with Subjects * must implement <code>Serializable</code>. * * @version 1.123, 05/05/04 * @see java.security.Principal * @see java.security.DomainCombiner */
/** * <p> <code>LoginModule</code> describes the interface * implemented by authentication technology providers. LoginModules * are plugged in under applications to provide a particular type of * authentication. * * <p> While applications write to the <code>LoginContext</code> API, * authentication technology providers implement the * <code>LoginModule</code> interface. * A <code>Configuration</code> specifies the LoginModule(s) * to be used with a particular login application. Therefore different * LoginModules can be plugged in under the application without * requiring any modifications to the application itself. * *... */
PasswordLoginModule.java:
package com.wgu.jaas; import java.io.IOException; import java.security.Principal; import java.util.Map; 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.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; public class PasswordLoginModule implements LoginModule { public static final String USER_NAME = "jaas"; /* * A <code>Subject</code> represents a grouping of related information for * a single entity, such as a person. It present a entity who will * manipulate the system. */ private Subject mySubject; private CallbackHandler myCallbackHandler; private String username; private char[] password; private boolean loginSucceeded = false; private boolean commitSucceeded = false; /* * This interface represents the abstract notion of a principal, which can * be used to represent any entity, such as an individual, a corporation, * and a login id. * */ private Principal myPrincipal; /** * abort() will be called if overall login failed. */ public boolean abort() throws LoginException { return false; } /** * This is called once the login successed. */ public boolean commit() throws LoginException { if (!this.loginSucceeded) { return false; } myPrincipal = new PrincipalImpl(username); // create a Principal and add it to Subject. if (!mySubject.getPrincipals().contains(myPrincipal)) { mySubject.getPrincipals().add(myPrincipal); } username = null; clearPassword(); commitSucceeded = true; return true; } /** * Initialize the LoginModule according to configuration. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) { this.mySubject = subject; this.myCallbackHandler = callbackHandler; loginSucceeded = false; commitSucceeded = false; username = null; clearPassword(); } private void clearPassword() { if (this.password == null) { return; } for (char c : password) { c = (char) ' '; } password = null; } /** * Attempt to log a user in. */ public boolean login() throws LoginException { if (myCallbackHandler == null) { throw new LoginException("No CallbackHandler defined."); } /* * Implementations of this interface are passed to a <code>CallbackHandler</code>, * allowing underlying security services the ability to interact with a * calling application to retrieve specific authentication data such as * usernames and passwords, or to display certain information, such as * error and warning messages. */ Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback("UserName"); callbacks[1] = new PasswordCallback("Password", false); try { myCallbackHandler.handle(callbacks); username = ((NameCallback) callbacks[0]).getName(); char[] tempPsw = ((PasswordCallback) callbacks[1]).getPassword(); password = new char[tempPsw.length]; System.arraycopy(tempPsw, 0, password, 0, tempPsw.length); ((PasswordCallback) callbacks[1]).clearPassword(); } catch (IOException e) { throw new LoginException(e.getMessage()); } catch (UnsupportedCallbackException e) { throw new LoginException(e.getMessage()); } // we can update this component to check user/psw against database. if (username.equals(USER_NAME) && password.length == USER_NAME.length()) { loginSucceeded = true; return true; } else { loginSucceeded = false; username = null; clearPassword(); return false; } } /** * Logout user. It will remove Principal from Subject. */ public boolean logout() throws LoginException { mySubject.getPrincipals().remove(myPrincipal); loginSucceeded = false; commitSucceeded = false; username = null; clearPassword(); myPrincipal = null; return true; } public static void main(String[] args) { char[] a = { 'a', 'b', 'c' }; char[] b = a; // a = null; for (char c : a) { c = (char) ' '; } for (char c : b) { System.out.println(c); } } }
UserNamePasswordCallbackHandler.java:
/** * */ package com.wgu.jaas; import java.io.IOException; 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.callback.UnsupportedCallbackException; /** * @author wgu * */ public class UserNamePasswordCallbackHandler implements CallbackHandler { String username; char[] password; public UserNamePasswordCallbackHandler(String username, char[] password) { this.username = username; this.password = password; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { NameCallback nameCb = (NameCallback) callback; nameCb.setName(username); } else if (callback instanceof PasswordCallback) { PasswordCallback pswCb = (PasswordCallback) callback; pswCb.setPassword(password); } } } }
PrincipalImpl.java:
/** * */ package com.wgu.jaas; import java.io.Serializable; import java.security.Principal; /** * @author Administrator * */ public class PrincipalImpl implements Principal, Serializable { private String name; public PrincipalImpl(String name) { this.name = name; } @Override public int hashCode() { return name.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final PrincipalImpl other = (PrincipalImpl) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public String getName() { return name; } public String toString() { return getName(); } }
JAASTest.java:
/** * */ package com.wgu.jaas; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; /** * @author wgu * */ public class JAASTest { /** * We have to config "-Djava.security.auth.login.config=jaas.config" to * specify configuration file. * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { LoginContext lc = new LoginContext("JAASSample", new UserNamePasswordCallbackHandler()); try { lc.login(); } catch (LoginException e) { // Authentication failed. } // Authentication successful, we can now continue. // We can use the returned Subject if we like. Subject sub = lc.getSubject(); System.out.println(sub); } }
jaas.config:
JAASSample { com.wgu.jaas.PasswordLoginModule required option1="I am option";
};
JAASPriveligedActionExample.java:
package com.wgu.jaas; import java.security.PrivilegedAction; public class JAASPriveligedActionExample implements PrivilegedAction { public Object run() { System.out.println("Secret text: " + JAASAuthorizationExample.getSecretText()); return null; } }
JAASAuthorizationExample.java:
package com.wgu.jaas; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Principal; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; public class JAASAuthorizationExample { private static final String NO_PRINCIPAL = "NO_PRINCIPAL"; public static String getSecretText() { AccessControlContext context = AccessController.getContext(); Subject sub2 = Subject.getSubject(context); if (sub2 == null) { return NO_PRINCIPAL; } for (Principal p : sub2.getPrincipals()) { if (p.getName().equals(PasswordLoginModule.USER_NAME)) { return "PRINCIPAL_OK"; } } return NO_PRINCIPAL; } /** * We have to config "-Djava.security.auth.login.config=jaas.config" to * specify configuration file. * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { LoginContext lc = new LoginContext("JAASSample", new UserNamePasswordCallbackHandler()); try { lc.login(); } catch (LoginException e) { // Authentication failed. } // Authentication successful, we can now continue. // We can use the returned Subject if we like. Subject sub = lc.getSubject(); /* * Perform work as a particular <code>Subject</code>. * */ Subject.doAs(sub, new JAASPriveligedActionExample()); } }