/**
* <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());
}
}