KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > jetty > servlet > FormAuthenticator


1 // ========================================================================
2
// $Id: FormAuthenticator.java,v 1.32 2005/08/13 00:01:27 gregwilkins Exp $
3
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.jetty.servlet;
17
18 import java.io.IOException JavaDoc;
19 import java.io.Serializable JavaDoc;
20 import java.security.Principal JavaDoc;
21
22 import javax.servlet.http.HttpServletRequest JavaDoc;
23 import javax.servlet.http.HttpServletResponse JavaDoc;
24 import javax.servlet.http.HttpSession JavaDoc;
25 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
26 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.mortbay.log.LogFactory;
30 import org.mortbay.http.Authenticator;
31 import org.mortbay.http.HttpRequest;
32 import org.mortbay.http.HttpResponse;
33 import org.mortbay.http.SSORealm;
34 import org.mortbay.http.SecurityConstraint;
35 import org.mortbay.http.UserRealm;
36 import org.mortbay.util.Credential;
37 import org.mortbay.util.Password;
38 import org.mortbay.util.URI;
39
40 /* ------------------------------------------------------------ */
41 /** FORM Authentication Authenticator.
42  * The HTTP Session is used to store the authentication status of the
43  * user, which can be distributed.
44  * If the realm implements SSORealm, SSO is supported.
45  *
46  * @version $Id: FormAuthenticator.java,v 1.32 2005/08/13 00:01:27 gregwilkins Exp $
47  * @author Greg Wilkins (gregw)
48  * @author dan@greening.name
49  */

50 public class FormAuthenticator implements Authenticator
51 {
52     static Log log = LogFactory.getLog(FormAuthenticator.class);
53
54     /* ------------------------------------------------------------ */
55     public final static String JavaDoc __J_URI="org.mortbay.jetty.URI";
56     public final static String JavaDoc __J_AUTHENTICATED="org.mortbay.jetty.Auth";
57     public final static String JavaDoc __J_SECURITY_CHECK="j_security_check";
58     public final static String JavaDoc __J_USERNAME="j_username";
59     public final static String JavaDoc __J_PASSWORD="j_password";
60
61     private String JavaDoc _formErrorPage;
62     private String JavaDoc _formErrorPath;
63     private String JavaDoc _formLoginPage;
64     private String JavaDoc _formLoginPath;
65     
66     /* ------------------------------------------------------------ */
67     public String JavaDoc getAuthMethod()
68     {
69         return HttpServletRequest.FORM_AUTH;
70     }
71
72     /* ------------------------------------------------------------ */
73     public void setLoginPage(String JavaDoc path)
74     {
75         if (!path.startsWith("/"))
76         {
77             log.warn("form-login-page must start with /");
78             path="/"+path;
79         }
80         _formLoginPage=path;
81         _formLoginPath=path;
82         if (_formLoginPath.indexOf('?')>0)
83             _formLoginPath=_formLoginPath.substring(0,_formLoginPath.indexOf('?'));
84     }
85
86     /* ------------------------------------------------------------ */
87     public String JavaDoc getLoginPage()
88     {
89         return _formLoginPage;
90     }
91     
92     /* ------------------------------------------------------------ */
93     public void setErrorPage(String JavaDoc path)
94     {
95         if (path==null || path.trim().length()==0)
96         {
97             _formErrorPath=null;
98             _formErrorPage=null;
99         }
100         else
101         {
102             if (!path.startsWith("/"))
103             {
104                 log.warn("form-error-page must start with /");
105                 path="/"+path;
106             }
107             _formErrorPage=path;
108             _formErrorPath=path;
109
110             if (_formErrorPath!=null && _formErrorPath.indexOf('?')>0)
111                 _formErrorPath=_formErrorPath.substring(0,_formErrorPath.indexOf('?'));
112         }
113     }
114
115     /* ------------------------------------------------------------ */
116     public String JavaDoc getErrorPage()
117     {
118         return _formErrorPage;
119     }
120     
121     /* ------------------------------------------------------------ */
122     /** Perform form authentication.
123      * Called from SecurityHandler.
124      * @return UserPrincipal if authenticated else null.
125      */

126     public Principal JavaDoc authenticate(UserRealm realm,
127                                   String JavaDoc pathInContext,
128                                   HttpRequest httpRequest,
129                                   HttpResponse httpResponse)
130         throws IOException JavaDoc
131     {
132         HttpServletRequest JavaDoc request =(ServletHttpRequest)httpRequest.getWrapper();
133         HttpServletResponse JavaDoc response = httpResponse==null?null:(HttpServletResponse JavaDoc) httpResponse.getWrapper();
134         
135         // Handle paths
136
String JavaDoc uri = pathInContext;
137
138         // Setup session
139
HttpSession JavaDoc session=request.getSession(response!=null);
140         if (session==null)
141             return null;
142         
143         // Handle a request for authentication.
144
if ( uri.substring(uri.lastIndexOf("/")+1).startsWith(__J_SECURITY_CHECK) )
145         {
146             // Check the session object for login info.
147
FormCredential form_cred=new FormCredential();
148             form_cred.authenticate(realm,
149                                             request.getParameter(__J_USERNAME),
150                                             request.getParameter(__J_PASSWORD),
151                                             httpRequest);
152             
153             String JavaDoc nuri=(String JavaDoc)session.getAttribute(__J_URI);
154             if (nuri==null || nuri.length()==0)
155             {
156                 nuri=request.getContextPath();
157                 if (nuri.length()==0)
158                     nuri="/";
159             }
160             
161             if (form_cred._userPrincipal!=null)
162             {
163                 // Authenticated OK
164
if(log.isDebugEnabled())log.debug("Form authentication OK for "+form_cred._jUserName);
165                 session.removeAttribute(__J_URI); // Remove popped return URI.
166
httpRequest.setAuthType(SecurityConstraint.__FORM_AUTH);
167                 httpRequest.setAuthUser(form_cred._jUserName);
168                 httpRequest.setUserPrincipal(form_cred._userPrincipal);
169                 session.setAttribute(__J_AUTHENTICATED,form_cred);
170
171                 // Sign-on to SSO mechanism
172
if (realm instanceof SSORealm)
173                 {
174                     ((SSORealm)realm).setSingleSignOn(httpRequest,
175                                                                     httpResponse,
176                                                                     form_cred._userPrincipal,
177                                                                     new Password(form_cred._jPassword));
178                 }
179
180                 // Redirect to original request
181
if (response!=null)
182                 {
183                     response.setContentLength(0);
184                     response.sendRedirect(response.encodeRedirectURL(nuri));
185                 }
186             }
187             else if (response!=null)
188             {
189                 if(log.isDebugEnabled())log.debug("Form authentication FAILED for "+form_cred._jUserName);
190                 if (_formErrorPage!=null)
191                 {
192                     response.setContentLength(0);
193                     response.sendRedirect(response.encodeRedirectURL
194                                           (URI.addPaths(request.getContextPath(),
195                                                         _formErrorPage)));
196                 }
197                 else
198                 {
199                     response.sendError(HttpResponse.__403_Forbidden);
200                 }
201             }
202             
203             // Security check is always false, only true after final redirection.
204
return null;
205         }
206         
207         // Check if the session is already authenticated.
208
FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
209         
210         if (form_cred != null)
211         {
212             // We have a form credential. Has it been distributed?
213
if (form_cred._userPrincipal==null)
214             {
215                 // This form_cred appears to have been distributed. Need to reauth
216
form_cred.authenticate(realm, httpRequest);
217                 
218                 // Sign-on to SSO mechanism
219
if (form_cred._userPrincipal!=null && realm instanceof SSORealm)
220                 {
221                     ((SSORealm)realm).setSingleSignOn(httpRequest,
222                                                                     httpResponse,
223                                                                     form_cred._userPrincipal,
224                                                                     new Password(form_cred._jPassword));
225                 }
226             }
227             else if (!realm.reauthenticate(form_cred._userPrincipal))
228                 // Else check that it is still authenticated.
229
form_cred._userPrincipal=null;
230
231             // If this credential is still authenticated
232
if (form_cred._userPrincipal!=null)
233             {
234                 if(log.isDebugEnabled())log.debug("FORM Authenticated for "+form_cred._userPrincipal.getName());
235                 httpRequest.setAuthType(SecurityConstraint.__FORM_AUTH);
236                 httpRequest.setAuthUser(form_cred._userPrincipal.getName());
237                 httpRequest.setUserPrincipal(form_cred._userPrincipal);
238                 return form_cred._userPrincipal;
239             }
240             else
241                 session.setAttribute(__J_AUTHENTICATED,null);
242         }
243         else if (realm instanceof SSORealm)
244         {
245             // Try a single sign on.
246
Credential cred = ((SSORealm)realm).getSingleSignOn(httpRequest,httpResponse);
247             
248             if (httpRequest.hasUserPrincipal())
249             {
250                 form_cred=new FormCredential();
251                 form_cred._userPrincipal=request.getUserPrincipal();
252                 form_cred._jUserName=form_cred._userPrincipal.getName();
253                 if (cred!=null)
254                     form_cred._jPassword=cred.toString();
255                 if(log.isDebugEnabled())log.debug("SSO for "+form_cred._userPrincipal);
256                            
257                 httpRequest.setAuthType(SecurityConstraint.__FORM_AUTH);
258                 session.setAttribute(__J_AUTHENTICATED,form_cred);
259                 return form_cred._userPrincipal;
260             }
261         }
262         
263         // Don't authenticate authform or errorpage
264
if (isLoginOrErrorPage(pathInContext))
265             return SecurityConstraint.__NOBODY;
266         
267         // redirect to login page
268
if (response!=null)
269         {
270             if (httpRequest.getQuery()!=null)
271                 uri+="?"+httpRequest.getQuery();
272             session.setAttribute(__J_URI,
273                                  request.getScheme() +
274                                  "://" + request.getServerName() +
275                                  ":" + request.getServerPort() +
276                                  URI.addPaths(request.getContextPath(),uri));
277             response.setContentLength(0);
278             response.sendRedirect(response.encodeRedirectURL(URI.addPaths(request.getContextPath(),
279                                                                           _formLoginPage)));
280         }
281
282         return null;
283     }
284
285     public boolean isLoginOrErrorPage(String JavaDoc pathInContext)
286     {
287         return pathInContext!=null &&
288          (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
289     }
290     
291     /* ------------------------------------------------------------ */
292     /** FORM Authentication credential holder.
293      */

294     private static class FormCredential implements Serializable JavaDoc, HttpSessionBindingListener JavaDoc
295     {
296         String JavaDoc _jUserName;
297         String JavaDoc _jPassword;
298         transient Principal JavaDoc _userPrincipal;
299         transient UserRealm _realm;
300
301         void authenticate(UserRealm realm,String JavaDoc user,String JavaDoc password,HttpRequest request)
302         {
303             _jUserName=user;
304             _jPassword=password;
305             _userPrincipal = realm.authenticate(user, password, request);
306             if (_userPrincipal!=null)
307                 _realm=realm;
308         }
309
310         void authenticate(UserRealm realm,HttpRequest request)
311         {
312             _userPrincipal = realm.authenticate(_jUserName, _jPassword, request);
313             if (_userPrincipal!=null)
314                 _realm=realm;
315         }
316         
317
318         public void valueBound(HttpSessionBindingEvent JavaDoc event) {}
319         
320         public void valueUnbound(HttpSessionBindingEvent JavaDoc event)
321         {
322             if(log.isDebugEnabled())log.debug("Logout "+_jUserName);
323             
324             if(_realm instanceof SSORealm)
325                 ((SSORealm)_realm).clearSingleSignOn(_jUserName);
326                
327             if(_realm!=null && _userPrincipal!=null)
328                 _realm.logout(_userPrincipal);
329         }
330         
331         public int hashCode()
332         {
333             return _jUserName.hashCode()+_jPassword.hashCode();
334         }
335
336         public boolean equals(Object JavaDoc o)
337         {
338             if (!(o instanceof FormCredential))
339                 return false;
340             FormCredential fc = (FormCredential)o;
341             return
342                 _jUserName.equals(fc._jUserName) &&
343                 _jPassword.equals(fc._jPassword);
344         }
345
346         public String JavaDoc toString()
347         {
348             return "Cred["+_jUserName+"]";
349         }
350
351     }
352 }
353
Popular Tags