KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > net > axis > server > JBossAuthenticationHandler


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7
8 // $Id: JBossAuthenticationHandler.java,v 1.6.6.3 2005/03/03 21:01:23 tdiesler Exp $
9

10 package org.jboss.net.axis.server;
11
12 import org.jboss.axis.AxisFault;
13 import org.jboss.axis.MessageContext;
14 import org.jboss.axis.handlers.BasicHandler;
15 import org.jboss.security.NobodyPrincipal;
16 import org.jboss.security.SecurityAssociation;
17 import org.jboss.security.SimplePrincipal;
18 import org.jboss.security.SubjectSecurityManager;
19
20 import javax.naming.InitialContext JavaDoc;
21 import javax.naming.NamingException JavaDoc;
22 import javax.security.auth.Subject JavaDoc;
23 import java.security.Principal JavaDoc;
24
25 /**
26  * <p>
27  * AuthenticationHandler that interacts with a given JBoss autentication
28  * manager via default simple principals and passchars from the
29  * HTTP Basic Authentication.
30  * </p>
31  * <p>
32  * It is derived from org.jboss.axis.handlers.SimpleAuthenticationHandler.
33  * Note that this is somehow redundant to the WebContainer security, but we want
34  * to be able to install different authentication schemes for different
35  * web services behind a single entry-point.
36  * </p>
37  * <p>
38  * Per default, unauthenticated calls will be routed by NOT asking the
39  * jboss auth manager for validation (most domains still would refuse NobodyPrincipal,
40  * no matter how configured) and building a "null" security association.
41  * </p>
42  * <p>
43  * By specifiying the validateUnauthenticatedCalls=true option, the handler
44  * will however try to interface the securityManager with the NobodyPrincipal and
45  * an empty password and ask for a proper security association. This is
46  * important when dealing with MS Clients (thanks to John Landers for pointing
47  * this out) that won�t send any authentication data if not confronted with
48  * an HTTP error on the first try.
49  * </p>
50  * @author <a HREF="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a>
51  * @since 14.03.2002
52  * @version $Revision: 1.6.6.3 $
53  */

54 public class JBossAuthenticationHandler extends BasicHandler
55 {
56
57    //
58
// Attributes
59
//
60

61    /** whether this handler has been initialized already */
62    protected boolean isInitialised;
63
64    /** whether this handler should let through unauthenticated calls */
65    protected boolean shouldValidateUnauthenticatedCalls;
66
67    /**
68     * this is the authentication manager that is responsible for our security domain
69     * if that is null, this authenticationhandler will block any call, rather deactivate
70     * the handler, then, or run against a NullSecurityManager
71     */

72    protected SubjectSecurityManager authMgr;
73
74    //
75
// Constructors
76
//
77

78    /** default, all options are set afterwards */
79    public JBossAuthenticationHandler()
80    {
81    }
82
83    //
84
// Protected helpers
85
//
86

87    /**
88     * initialize this authenticationhandler lazy, after the options have been
89     * set.
90     */

91    protected void initialise() throws AxisFault
92    {
93       isInitialised = true;
94       authMgr = null;
95       shouldValidateUnauthenticatedCalls = false;
96       String JavaDoc securityDomain = (String JavaDoc)getOption(Constants.SECURITY_DOMAIN_OPTION);
97       if (securityDomain != null)
98       {
99          try
100          {
101             // bind against the jboss security subsystem
102
authMgr =
103                     (SubjectSecurityManager)new InitialContext JavaDoc().lookup(securityDomain);
104          }
105          catch (NamingException JavaDoc e)
106          {
107             throw new AxisFault("Could not lookup associated security domain " + securityDomain,
108                     e);
109          }
110       }
111       String JavaDoc unauthenticatedCalls = (String JavaDoc)getOption(Constants.VALIDATE_UNAUTHENTICATED_CALLS_OPTION);
112       if (unauthenticatedCalls != null)
113       {
114          try
115          {
116             // bind against the jboss security subsystem
117
shouldValidateUnauthenticatedCalls = new Boolean JavaDoc(unauthenticatedCalls).booleanValue();
118          }
119          catch (Exception JavaDoc e)
120          {
121             throw new AxisFault("Could not set validateUnauthenticatedCalls option.", e);
122          }
123       }
124    }
125
126    /**
127     * creates a new principal belonging to the given username,
128     * override to adapt to specific security domains.
129     */

130    protected Principal getPrincipal(String JavaDoc userName)
131    {
132       if (userName == null)
133       {
134          return NobodyPrincipal.NOBODY_PRINCIPAL;
135       }
136       else
137       {
138          return new SimplePrincipal(userName);
139       }
140    }
141
142    /** validates the given principal with the given password */
143    protected Subject JavaDoc validate(Principal userPrincipal, String JavaDoc passwd) throws AxisFault
144    {
145       // build passchars
146
char[] passChars = passwd != null ? passwd.toCharArray() : null;
147       // do the validation only if authenticated or validation enforced
148
Subject JavaDoc subject = null;
149       if (shouldValidateUnauthenticatedCalls || userPrincipal != NobodyPrincipal.NOBODY_PRINCIPAL)
150       {
151          subject = new Subject JavaDoc();
152          // have to use pointer comparison here, but it�s a singleton, right?
153
if (!authMgr.isValid(userPrincipal, passChars, subject))
154          {
155             throw new AxisFault("Server.Unauthenticated",
156                     org.jboss.axis.utils.Messages.getMessage
157                     ("cantAuth01",
158                             userPrincipal.getName()),
159                     null, null);
160          }
161       }
162       return subject;
163    }
164
165    /** associates the call context with the given info */
166    protected void associate(Principal userPrincipal, String JavaDoc passwd, Subject JavaDoc subject)
167    {
168       // pointer comparison, again
169
if (shouldValidateUnauthenticatedCalls || userPrincipal != NobodyPrincipal.NOBODY_PRINCIPAL)
170       {
171          SecurityAssociation.pushSubjectContext(subject, userPrincipal, passwd);
172       }
173       else
174       {
175          // Jboss security normally does not like nobody:null
176
SecurityAssociation.setPrincipal(null);
177          SecurityAssociation.setCredential(null);
178       }
179    }
180
181    //
182
// API
183
//
184

185    /**
186     * Authenticate the user and password from the msgContext. Note that
187     * we do not disassociate the subject here, since that would have
188     * to be done by a separate handler in the response chain and we
189     * currently expect Jetty or the WebContainer to do that for us
190     */

191
192    public void invoke(MessageContext msgContext) throws AxisFault
193    {
194
195       // double check does not work on multiple processors, unfortunately
196
if (!isInitialised)
197       {
198          synchronized (this)
199          {
200             if (!isInitialised)
201             {
202                initialise();
203             }
204          }
205       }
206
207       if (authMgr == null)
208       {
209          throw new AxisFault("No security domain associated.");
210       }
211
212       // we take the id out of the
213
String JavaDoc userID = msgContext.getUsername();
214       // convert into a principal
215
Principal userPrincipal = getPrincipal(userID);
216       // the password that has been provided
217
String JavaDoc passwd = msgContext.getPassword();
218       // validate the user
219
Subject JavaDoc subject = validate(userPrincipal, passwd);
220       // associate the context
221
associate(userPrincipal, passwd, subject);
222       // with the security subject
223
msgContext.setProperty(MessageContext.AUTHUSER, subject);
224    }
225
226 }
Popular Tags