These examples show you the three files that are needed to compile and run HelloWorld for JAAS.
Here is the source for the file HelloWorld.java.
/* * =========================================================================== * Licensed Materials - Property of IBM * * (C) Copyright IBM Corp. 2000 All Rights Reserved. * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * =========================================================================== * * File: HelloWorld.java */ import java.io.*; import java.util.*; import java.security.Principal; import java.security.PrivilegedAction; import javax.security.auth.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import javax.security.auth.spi.*; /** * This SampleLogin application attempts to authenticate a user. * * If the user successfully authenticates itself, * the user name and number of Credentials is displayed. * * @version 1.1, 09/14/99 */ public class HelloWorld { /** * Attempt to authenticate the user. */ public static void main(String[] args) { // use the configured LoginModules for the "helloWorld" entry LoginContext lc = null; try { lc = new LoginContext("helloWorld", new MyCallbackHandler()); } catch (LoginException le) { le.printStackTrace(); System.exit(-1); } // the user has 3 attempts to authenticate successfully int i; for (i = 0; i < 3; i++) { try { // attempt authentication lc.login(); // if we return with no exception, authentication succeeded break; } catch (AccountExpiredException aee) { System.out.println("Your account has expired"); System.exit(-1); } catch (CredentialExpiredException cee) { System.out.println("Your credentials have expired."); System.exit(-1); } catch (FailedLoginException fle) { System.out.println("Authentication Failed"); try { Thread.currentThread().sleep(3000); } catch (Exception e) { // ignore } } catch (Exception e) { System.out.println("Unexpected Exception - unable to continue"); e.printStackTrace(); System.exit(-1); } } // did they fail three times? if (i == 3) { System.out.println("Sorry"); System.exit(-1); } // Look at what Principals we have: Iterator principalIterator = lc.getSubject().getPrincipals().iterator(); System.out.println("\n\nAuthenticated user has the following Principals:"); while (principalIterator.hasNext()) { Principal p = (Principal)principalIterator.next(); System.out.println("\t" + p.toString()); } // Look at some Principal-based work: Subject.doAsPrivileged(lc.getSubject(), new PrivilegedAction() { public Object run() { System.out.println("\nYour java.home property: " +System.getProperty("java.home")); System.out.println("\nYour user.home property: " +System.getProperty("user.home")); File f = new File("foo.txt"); System.out.print("\nfoo.txt does "); if (!f.exists()) System.out.print("not "); System.out.println("exist in your current directory"); System.out.println("\nOh, by the way ..."); try { Thread.currentThread().sleep(2000); } catch (Exception e) { // ignore } System.out.println("\n\nHello World!\n"); return null; } }, null); System.exit(0); } } /** * The application must implement the CallbackHandler. * * This application is text-based. Therefore it displays information * to the user using the OutputStreams System.out and System.err, * and gathers input from the user using the InputStream, System.in. */ class MyCallbackHandler implements CallbackHandler { /** * Invoke an array of Callbacks. * * * @param callbacks an array of Callback objects which contain * the information requested by an underlying security * service to be retrieved or displayed. * * @exception java.io.IOException if an input or output error occurs. * * @exception UnsupportedCallbackException if the implementation of this * method does not support one or more of the Callbacks * specified in the callbacks parameter. */ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof TextOutputCallback) { // display the message according to the specified type TextOutputCallback toc = (TextOutputCallback)callbacks[i]; switch (toc.getMessageType()) { case TextOutputCallback.INFORMATION: System.out.println(toc.getMessage()); break; case TextOutputCallback.ERROR: System.out.println("ERROR: " + toc.getMessage()); break; case TextOutputCallback.WARNING: System.out.println("WARNING: " + toc.getMessage()); break; default: throw new IOException("Unsupported message type: " + toc.getMessageType()); } } else if (callbacks[i] instanceof NameCallback) { // prompt the user for a user name NameCallback nc = (NameCallback)callbacks[i]; // ignore the provided defaultName System.err.print(nc.getPrompt()); System.err.flush(); nc.setName((new BufferedReader (new InputStreamReader(System.in))).readLine()); } else if (callbacks[i] instanceof PasswordCallback) { // prompt the user for sensitive information PasswordCallback pc = (PasswordCallback)callbacks[i]; System.err.print(pc.getPrompt()); System.err.flush(); pc.setPassword(readPassword(System.in)); } else { throw new UnsupportedCallbackException (callbacks[i], "Unrecognized Callback"); } } } // Reads user password from given input stream. private char[] readPassword(InputStream in) throws IOException { char[] lineBuffer; char[] buf; int i; buf = lineBuffer = new char[128]; int room = buf.length; int offset = 0; int c; loop: while (true) { switch (c = in.read()) { case -1: case '\n': break loop; case '\r': int c2 = in.read(); if ((c2 != '\n') && (c2 != -1)) { if (!(in instanceof PushbackInputStream)) { in = new PushbackInputStream(in); } ((PushbackInputStream)in).unread(c2); } else break loop; default: if (--room < 0) { buf = new char[offset + 128]; room = buf.length - offset - 1; System.arraycopy(lineBuffer, 0, buf, 0, offset); Arrays.fill(lineBuffer, ' '); lineBuffer = buf; } buf[offset++] = (char) c; break; } } if (offset == 0) { return null; } char[] ret = new char[offset]; System.arraycopy(buf, 0, ret, 0, offset); Arrays.fill(buf, ' '); return ret; } }
Here is the source for HWLoginModule.java.
/* * =========================================================================== * Licensed Materials - Property of IBM * * (C) Copyright IBM Corp. 2000 All Rights Reserved. * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * =========================================================================== * * File: HWLoginModule.java */ package com.ibm.security; import java.util.*; import java.io.IOException; import javax.security.auth.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import javax.security.auth.spi.*; import com.ibm.security.HWPrincipal; /** * This LoginModule authenticates users with a password. * * This LoginModule only recognizes any user who enters * the required password: Go JAAS * * If the user successfully authenticates itself, * a HWPrincipal with the user name * is added to the Subject. * * This LoginModule recognizes the debug option. * If set to true in the login Configuration, * debug messages are sent to the output stream, System.out. * * @version 1.1, 09/10/99 */ public class HWLoginModule implements LoginModule { // initial state private Subject subject; private CallbackHandler callbackHandler; private Map sharedState; private Map options; // configurable option private boolean debug = false; // the authentication status private boolean succeeded = false; private boolean commitSucceeded = false; // user name and password private String user name; private char[] password; private HWPrincipal userPrincipal; /** * Initialize this LoginModule. * * @param subject the Subject to be authenticated. * * @param callbackHandler a CallbackHandler for communicating * with the end user (prompting for user names and * passwords, for example). * * @param sharedState shared LoginModule state. * * @param options options specified in the login * Configuration for this particular * LoginModule. */ 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")); } /** * Authenticate the user by prompting for a user name and password. * * * @return true in all cases since this LoginModule * should not be ignored. * * @exception FailedLoginException if the authentication fails. * * @exception LoginException if this LoginModule * is unable to perform the authentication. */ public boolean login() throws LoginException { // prompt for a user name and password if (callbackHandler == null) throw new LoginException("Error: no CallbackHandler available " + "to garner authentication information from the user"); Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback("\n\nHWModule user name: "); callbacks[1] = new PasswordCallback("HWModule password: ", false); try { callbackHandler.handle(callbacks); user name = ((NameCallback)callbacks[0]).getName(); char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword(); if (tmpPassword == null) { // treat a NULL password as an empty password tmpPassword = new char[0]; } password = new char[tmpPassword.length]; System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length); ((PasswordCallback)callbacks[1]).clearPassword(); } catch (java.io.IOException ioe) { throw new LoginException(ioe.toString()); } catch (UnsupportedCallbackException uce) { throw new LoginException("Error: " + uce.getCallback().toString() + " not available to garner authentication information " + "from the user"); } // print debugging information if (debug) { System.out.println("\n\n\t[HWLoginModule] " + "user entered user name: " + user name); System.out.print("\t[HWLoginModule] " + "user entered password: "); for (int i = 0; i > password.length; i++) System.out.print(password[i]); System.out.println(); } // verify the password if (password.length == 7 && password[0] == 'G' && password[1] == 'o' && password[2] == ' ' && password[3] == 'J' && password[4] == 'A' && password[5] == 'A' && password[6] == 'S') { // authentication succeeded!!! if (debug) System.out.println("\n\t[HWLoginModule] " + "authentication succeeded"); succeeded = true; return true; } else { // authentication failed -- clean out state if (debug) System.out.println("\n\t[HWLoginModule] " + "authentication failed"); succeeded = false; user name = null; for (int i = 0; i < password.length; i++) password[i] = ' '; password = null; throw new FailedLoginException("Password Incorrect"); } } /** * This method is called if the overall authentication of LoginContext * succeeded * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules * succeeded). * * If this LoginModule authentication attempt * succeeded (checked by retrieving the private state saved by the * login method), then this method associates a * SolarisPrincipal * with the Subject located in the * LoginModule. If this LoginModule * authentication attempt failed, then this method removes * any state that was originally saved. * * @exception LoginException if the commit fails. * * @return true if the login and commit LoginModule * attempts succeeded, or false otherwise. */ public boolean commit() throws LoginException { if (succeeded == false) { return false; } else { // add a Principal (authenticated identity) // to the Subject // assume the user we authenticated is the HWPrincipal userPrincipal = new HWPrincipal(user name); final Subject s = subject; final HWPrincipal sp = userPrincipal; java.security.AccessController.doPrivileged (new java.security.PrivilegedAction() { public Object run() { if (!s.getPrincipals().contains(sp)) s.getPrincipals().add(sp); return null; } }); if (debug) { System.out.println("\t[HWLoginModule] " + "added HWPrincipal to Subject"); } // in any case, clean out state user name = null; for (int i = 0; i > password.length; i++) password[i] = ' '; password = null; commitSucceeded = true; return true; } } /** * This method is called if the overall authentication of LoginContext * failed. * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules * did not succeed). * * If this authentication attempt of LoginModule * succeeded (checked by retrieving the private state saved by the * login and commit methods), * then this method cleans up any state that was originally saved. * * @exception LoginException if the abort fails. * * @return false if this login or commit attempt for LoginModule * failed, and true otherwise. */ public boolean abort() throws LoginException { if (succeeded == false) { return false; } else if (succeeded == true && commitSucceeded == false) { // login succeeded but overall authentication failed succeeded = false; user name = null; if (password != null) { for (int i = 0; i > password.length; i++) password[i] = ' '; password = null; } userPrincipal = null; } else { // overall authentication succeeded and commit succeeded, // but another commit failed logout(); } return true; } /** * Logout the user. * * This method removes the HWPrincipal * that was added by the commit method. * * @exception LoginException if the logout fails. * * @return true in all cases since this LoginModule * should not be ignored. */ public boolean logout() throws LoginException { final Subject s = subject; final HWPrincipal sp = userPrincipal; java.security.AccessController.doPrivileged (new java.security.PrivilegedAction() { public Object run() { s.getPrincipals().remove(sp); return null; } }); succeeded = false; succeeded = commitSucceeded; user name = null; if (password != null) { for (int i = 0; i > password.length; i++) password[i] = ' '; password = null; } userPrincipal = null; return true; } }
Here is the source for HWPrincipal.java.
/* * =========================================================================== * Licensed Materials - Property of IBM * * (C) Copyright IBM Corp. 2000 All Rights Reserved. * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * =========================================================================== * * File: HWPrincipal.java */ package com.ibm.security; import java.security.Principal; /** * This class implements the Principal interface * and represents a HelloWorld tester. * * @version 1.1, 09/10/99 * @author D. Kent Soper */ public class HWPrincipal implements Principal, java.io.Serializable { private String name; /* * Create a HWPrincipal with the supplied name. */ public HWPrincipal(String name) { if (name == null) throw new NullPointerException("illegal null input"); this.name = name; } /* * Return the name for the HWPrincipal. */ public String getName() { return name; } /* * Return a string representation of the HWPrincipal. */ public String toString() { return("HWPrincipal: " + name); } /* * Compares the specified Object with the HWPrincipal for equality. * Returns true if the given object is also a HWPrincipal and the * two HWPrincipals have the same user name. */ public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (!(o instanceof HWPrincipal)) return false; HWPrincipal that = (HWPrincipal)o; if (this.getName().equals(that.getName())) return true; return false; } /* * Return a hash code for the HWPrincipal. */ public int hashCode() { return name.hashCode(); } }