| /* |
| * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| import java.security.Principal; |
| import java.util.Arrays; |
| 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.FailedLoginException; |
| import javax.security.auth.login.LoginException; |
| import javax.security.auth.spi.LoginModule; |
| |
| /** |
| * This code was based on JAAS demo code, small modification is made for testing |
| * purpose. |
| */ |
| public class SmartLoginModule implements LoginModule { |
| |
| // initial state |
| private Subject subject; |
| private CallbackHandler callbackHandler; |
| |
| // the authentication status |
| private boolean succeeded = false; |
| private boolean commitSucceeded = false; |
| |
| // username and password |
| private String username; |
| private char[] password; |
| |
| // Default values for this login module. In real world, |
| // don't do it in this way! |
| private String myUsername; |
| private char[] myPassword; |
| private String header; |
| |
| // testUser's SamplePrincipal |
| private SamplePrincipal userPrincipal; |
| |
| public SmartLoginModule() { |
| this("testUser", |
| new char[]{'t', 'e', 's', 't', 'P', 'a', 's', 's', |
| 'w', 'o', 'r', 'd', '1'}, |
| "SmartLoginModule1: "); |
| } |
| |
| public SmartLoginModule(String userName, char[] password, String header) { |
| myUsername = userName; |
| myPassword = password; |
| this.header = header; |
| } |
| |
| @Override |
| public boolean abort() throws LoginException { |
| if (!succeeded) { |
| return false; |
| } else if (succeeded && !commitSucceeded) { |
| // login succeeded but overall authentication failed |
| succeeded = false; |
| username = null; |
| password = null; |
| userPrincipal = null; |
| } else { |
| // overall authentication succeeded and commit succeeded, |
| // but someone else's commit failed |
| logout(); |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean commit() throws LoginException { |
| if (!succeeded) { |
| return false; |
| } else { |
| // add a Principal (authenticated identity) to the Subject |
| // assume the user we authenticated is the SamplePrincipal |
| userPrincipal = new SamplePrincipal(username); |
| if (!subject.getPrincipals().contains(userPrincipal)) { |
| subject.getPrincipals().add(userPrincipal); |
| } |
| // in any case, clean out state |
| username = null; |
| password = null; |
| commitSucceeded = true; |
| return true; |
| } |
| } |
| |
| @Override |
| public void initialize(Subject subject, CallbackHandler callbackHandler, |
| Map<String, ?> sharedState, Map<String, ?> options) { |
| this.subject = subject; |
| this.callbackHandler = callbackHandler; |
| } |
| |
| @Override |
| public boolean login() throws LoginException { |
| 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(header + "user name: "); |
| callbacks[1] = new PasswordCallback(header + "password: ", false); |
| |
| try { |
| callbackHandler.handle(callbacks); |
| username = ((NameCallback) callbacks[0]).getName(); |
| char[] tmpPassword |
| = ((PasswordCallback) callbacks[1]).getPassword(); |
| if (tmpPassword == null) { |
| 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 (LoginException) new LoginException().initCause(ioe); |
| } catch (UnsupportedCallbackException uce) { |
| throw new LoginException("Error: " + header |
| + uce.getCallback().toString() |
| + " not available to garner authentication information " |
| + "from the user"); |
| } |
| |
| // verify the username/password |
| if (username.equals(myUsername) |
| && Arrays.equals(password, myPassword)) { |
| System.out.println("\t\t" + header + " authentication succeeded"); |
| succeeded = true; |
| return true; |
| } else { |
| // authentication failed -- clean out state |
| System.out.println("\t\t" + header + " authentication failed"); |
| printDebugInfo(); |
| succeeded = false; |
| username = null; |
| password = null; |
| throw new FailedLoginException("User Name or Password Incorrect"); |
| } |
| } |
| |
| @Override |
| public boolean logout() throws LoginException { |
| subject.getPrincipals().remove(userPrincipal); |
| succeeded = false; |
| succeeded = commitSucceeded; |
| username = null; |
| password = null; |
| userPrincipal = null; |
| return true; |
| } |
| |
| // print debugging information |
| private void printDebugInfo() { |
| System.out.println("\t\t" + header + " correct user name: " |
| + myUsername); |
| System.out.println("\t\t" + header + " user entered user name: " |
| + username); |
| System.out.print("\t\t" + header + " correct password: "); |
| for (char c : myPassword) { |
| System.out.print(c); |
| } |
| System.out.println(); |
| System.out.print("\t\t" + header + " user entered password: "); |
| for (char c : password) { |
| System.out.print(c); |
| } |
| System.out.println(); |
| } |
| } |
| |
| class SamplePrincipal implements Principal, java.io.Serializable { |
| |
| /** |
| * @serial |
| */ |
| private String name; |
| |
| /** |
| * Create a SamplePrincipal with a Sample username. |
| * |
| * @param name the Sample username for this user. |
| * @exception NullPointerException if the <code>name</code> is |
| * <code>null</code>. |
| */ |
| public SamplePrincipal(String name) { |
| if (name == null) { |
| throw new NullPointerException("illegal null input"); |
| } |
| |
| this.name = name; |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| @Override |
| public String toString() { |
| return "SamplePrincipal: " + name; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o == null) { |
| return false; |
| } |
| |
| if (this == o) { |
| return true; |
| } |
| |
| if (!(o instanceof SamplePrincipal)) { |
| return false; |
| } |
| SamplePrincipal that = (SamplePrincipal) o; |
| |
| return this.getName().equals(that.getName()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return name.hashCode(); |
| } |
| } |