JBossAuthenticationHandler.java |
/* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ // $Id: JBossAuthenticationHandler.java,v 1.6.6.3 2005/03/03 21:01:23 tdiesler Exp $ package org.jboss.net.axis.server; import org.jboss.axis.AxisFault; import org.jboss.axis.MessageContext; import org.jboss.axis.handlers.BasicHandler; import org.jboss.security.NobodyPrincipal; import org.jboss.security.SecurityAssociation; import org.jboss.security.SimplePrincipal; import org.jboss.security.SubjectSecurityManager; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.Subject; import java.security.Principal; /** * <p> * AuthenticationHandler that interacts with a given JBoss autentication * manager via default simple principals and passchars from the * HTTP Basic Authentication. * </p> * <p> * It is derived from org.jboss.axis.handlers.SimpleAuthenticationHandler. * Note that this is somehow redundant to the WebContainer security, but we want * to be able to install different authentication schemes for different * web services behind a single entry-point. * </p> * <p> * Per default, unauthenticated calls will be routed by NOT asking the * jboss auth manager for validation (most domains still would refuse NobodyPrincipal, * no matter how configured) and building a "null" security association. * </p> * <p> * By specifiying the validateUnauthenticatedCalls=true option, the handler * will however try to interface the securityManager with the NobodyPrincipal and * an empty password and ask for a proper security association. This is * important when dealing with MS Clients (thanks to John Landers for pointing * this out) that won�t send any authentication data if not confronted with * an HTTP error on the first try. * </p> * @author <a href="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a> * @since 14.03.2002 * @version $Revision: 1.6.6.3 $ */ public class JBossAuthenticationHandler extends BasicHandler { // // Attributes // /** whether this handler has been initialized already */ protected boolean isInitialised; /** whether this handler should let through unauthenticated calls */ protected boolean shouldValidateUnauthenticatedCalls; /** * this is the authentication manager that is responsible for our security domain * if that is null, this authenticationhandler will block any call, rather deactivate * the handler, then, or run against a NullSecurityManager */ protected SubjectSecurityManager authMgr; // // Constructors // /** default, all options are set afterwards */ public JBossAuthenticationHandler() { } // // Protected helpers // /** * initialize this authenticationhandler lazy, after the options have been * set. */ protected void initialise() throws AxisFault { isInitialised = true; authMgr = null; shouldValidateUnauthenticatedCalls = false; String securityDomain = (String)getOption(Constants.SECURITY_DOMAIN_OPTION); if (securityDomain != null) { try { // bind against the jboss security subsystem authMgr = (SubjectSecurityManager)new InitialContext().lookup(securityDomain); } catch (NamingException e) { throw new AxisFault("Could not lookup associated security domain " + securityDomain, e); } } String unauthenticatedCalls = (String)getOption(Constants.VALIDATE_UNAUTHENTICATED_CALLS_OPTION); if (unauthenticatedCalls != null) { try { // bind against the jboss security subsystem shouldValidateUnauthenticatedCalls = new Boolean(unauthenticatedCalls).booleanValue(); } catch (Exception e) { throw new AxisFault("Could not set validateUnauthenticatedCalls option.", e); } } } /** * creates a new principal belonging to the given username, * override to adapt to specific security domains. */ protected Principal getPrincipal(String userName) { if (userName == null) { return NobodyPrincipal.NOBODY_PRINCIPAL; } else { return new SimplePrincipal(userName); } } /** validates the given principal with the given password */ protected Subject validate(Principal userPrincipal, String passwd) throws AxisFault { // build passchars char[] passChars = passwd != null ? passwd.toCharArray() : null; // do the validation only if authenticated or validation enforced Subject subject = null; if (shouldValidateUnauthenticatedCalls || userPrincipal != NobodyPrincipal.NOBODY_PRINCIPAL) { subject = new Subject(); // have to use pointer comparison here, but it�s a singleton, right? if (!authMgr.isValid(userPrincipal, passChars, subject)) { throw new AxisFault("Server.Unauthenticated", org.jboss.axis.utils.Messages.getMessage ("cantAuth01", userPrincipal.getName()), null, null); } } return subject; } /** associates the call context with the given info */ protected void associate(Principal userPrincipal, String passwd, Subject subject) { // pointer comparison, again if (shouldValidateUnauthenticatedCalls || userPrincipal != NobodyPrincipal.NOBODY_PRINCIPAL) { SecurityAssociation.pushSubjectContext(subject, userPrincipal, passwd); } else { // Jboss security normally does not like nobody:null SecurityAssociation.setPrincipal(null); SecurityAssociation.setCredential(null); } } // // API // /** * Authenticate the user and password from the msgContext. Note that * we do not disassociate the subject here, since that would have * to be done by a separate handler in the response chain and we * currently expect Jetty or the WebContainer to do that for us */ public void invoke(MessageContext msgContext) throws AxisFault { // double check does not work on multiple processors, unfortunately if (!isInitialised) { synchronized (this) { if (!isInitialised) { initialise(); } } } if (authMgr == null) { throw new AxisFault("No security domain associated."); } // we take the id out of the String userID = msgContext.getUsername(); // convert into a principal Principal userPrincipal = getPrincipal(userID); // the password that has been provided String passwd = msgContext.getPassword(); // validate the user Subject subject = validate(userPrincipal, passwd); // associate the context associate(userPrincipal, passwd, subject); // with the security subject msgContext.setProperty(MessageContext.AUTHUSER, subject); } }
JBossAuthenticationHandler.java |