1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.security;
16
17 import java.io.IOException;
18 import java.io.Serializable;
19 import java.security.Principal;
20
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23 import javax.servlet.http.HttpSession;
24 import javax.servlet.http.HttpSessionBindingEvent;
25 import javax.servlet.http.HttpSessionBindingListener;
26
27 import org.mortbay.jetty.Request;
28 import org.mortbay.jetty.Response;
29 import org.mortbay.log.Log;
30 import org.mortbay.util.StringUtil;
31 import org.mortbay.util.URIUtil;
32
33
34
35
36
37
38
39
40
41
42
43 public class FormAuthenticator implements Authenticator
44 {
45
46 public final static String __J_URI="org.mortbay.jetty.URI";
47 public final static String __J_AUTHENTICATED="org.mortbay.jetty.Auth";
48 public final static String __J_SECURITY_CHECK="/j_security_check";
49 public final static String __J_USERNAME="j_username";
50 public final static String __J_PASSWORD="j_password";
51
52 private String _formErrorPage;
53 private String _formErrorPath;
54 private String _formLoginPage;
55 private String _formLoginPath;
56
57
58 public String getAuthMethod()
59 {
60 return HttpServletRequest.FORM_AUTH;
61 }
62
63
64 public void setLoginPage(String path)
65 {
66 if (!path.startsWith("/"))
67 {
68 Log.warn("form-login-page must start with /");
69 path="/"+path;
70 }
71 _formLoginPage=path;
72 _formLoginPath=path;
73 if (_formLoginPath.indexOf('?')>0)
74 _formLoginPath=_formLoginPath.substring(0,_formLoginPath.indexOf('?'));
75 }
76
77
78 public String getLoginPage()
79 {
80 return _formLoginPage;
81 }
82
83
84 public void setErrorPage(String path)
85 {
86 if (path==null || path.trim().length()==0)
87 {
88 _formErrorPath=null;
89 _formErrorPage=null;
90 }
91 else
92 {
93 if (!path.startsWith("/"))
94 {
95 Log.warn("form-error-page must start with /");
96 path="/"+path;
97 }
98 _formErrorPage=path;
99 _formErrorPath=path;
100
101 if (_formErrorPath!=null && _formErrorPath.indexOf('?')>0)
102 _formErrorPath=_formErrorPath.substring(0,_formErrorPath.indexOf('?'));
103 }
104 }
105
106
107 public String getErrorPage()
108 {
109 return _formErrorPage;
110 }
111
112
113
114
115
116
117 public Principal authenticate(UserRealm realm,
118 String pathInContext,
119 Request request,
120 Response response)
121 throws IOException
122 {
123
124 String uri = pathInContext;
125
126
127 HttpSession session=request.getSession(response!=null);
128 if (session==null)
129 return null;
130
131
132 if (isJSecurityCheck(uri) )
133 {
134
135 FormCredential form_cred=new FormCredential();
136 form_cred.authenticate(realm,
137 request.getParameter(__J_USERNAME),
138 request.getParameter(__J_PASSWORD),
139 request);
140
141 String nuri=(String)session.getAttribute(__J_URI);
142 if (nuri==null || nuri.length()==0)
143 {
144 nuri=request.getContextPath();
145 if (nuri.length()==0)
146 nuri=URIUtil.SLASH;
147 }
148
149 if (form_cred._userPrincipal!=null)
150 {
151
152 if(Log.isDebugEnabled())Log.debug("Form authentication OK for "+form_cred._jUserName);
153 session.removeAttribute(__J_URI);
154 request.setAuthType(Constraint.__FORM_AUTH);
155 request.setUserPrincipal(form_cred._userPrincipal);
156 session.setAttribute(__J_AUTHENTICATED,form_cred);
157
158
159 if (realm instanceof SSORealm)
160 ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new Password(form_cred._jPassword));
161
162
163 if (response != null)
164 {
165 response.setContentLength(0);
166 response.sendRedirect(response.encodeRedirectURL(nuri));
167 }
168 }
169 else
170 {
171 if(Log.isDebugEnabled())Log.debug("Form authentication FAILED for "+StringUtil.printable(form_cred._jUserName));
172
173 if (response!=null)
174 {
175 if (_formErrorPage==null)
176 {
177 response.sendError(HttpServletResponse.SC_FORBIDDEN);
178 }
179 else
180 {
181 response.setContentLength(0);
182 response.sendRedirect(response.encodeRedirectURL
183 (URIUtil.addPaths(request.getContextPath(),
184 _formErrorPage)));
185 }
186 }
187 }
188
189
190 return null;
191 }
192
193
194 FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
195
196 if (form_cred != null)
197 {
198
199 if (form_cred._userPrincipal==null)
200 {
201
202 form_cred.authenticate(realm, request);
203
204
205 if (form_cred._userPrincipal!=null && realm instanceof SSORealm)
206 ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new Password(form_cred._jPassword));
207
208 }
209 else if (!realm.reauthenticate(form_cred._userPrincipal))
210
211 form_cred._userPrincipal=null;
212
213
214 if (form_cred._userPrincipal!=null)
215 {
216 if(Log.isDebugEnabled())Log.debug("FORM Authenticated for "+form_cred._userPrincipal.getName());
217 request.setAuthType(Constraint.__FORM_AUTH);
218 request.setUserPrincipal(form_cred._userPrincipal);
219 return form_cred._userPrincipal;
220 }
221 else
222 session.setAttribute(__J_AUTHENTICATED,null);
223 }
224 else if (realm instanceof SSORealm)
225 {
226
227 Credential cred = ((SSORealm)realm).getSingleSignOn(request,response);
228
229 if (request.getUserPrincipal()!=null)
230 {
231 form_cred=new FormCredential();
232 form_cred._userPrincipal=request.getUserPrincipal();
233 form_cred._jUserName=form_cred._userPrincipal.getName();
234 if (cred!=null)
235 form_cred._jPassword=cred.toString();
236 if(Log.isDebugEnabled())Log.debug("SSO for "+form_cred._userPrincipal);
237
238 request.setAuthType(Constraint.__FORM_AUTH);
239 session.setAttribute(__J_AUTHENTICATED,form_cred);
240 return form_cred._userPrincipal;
241 }
242 }
243
244
245 if (isLoginOrErrorPage(pathInContext))
246 return SecurityHandler.__NOBODY;
247
248
249 if (response!=null)
250 {
251 if (request.getQueryString()!=null)
252 uri+="?"+request.getQueryString();
253 session.setAttribute(__J_URI,
254 request.getScheme() +
255 "://" + request.getServerName() +
256 ":" + request.getServerPort() +
257 URIUtil.addPaths(request.getContextPath(),uri));
258 response.setContentLength(0);
259 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(),
260 _formLoginPage)));
261 }
262
263 return null;
264 }
265
266
267 public boolean isLoginOrErrorPage(String pathInContext)
268 {
269 return pathInContext!=null &&
270 (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
271 }
272
273
274 public boolean isJSecurityCheck(String uri)
275 {
276 int jsc = uri.indexOf(__J_SECURITY_CHECK);
277
278 if (jsc<0)
279 return false;
280 int e=jsc+__J_SECURITY_CHECK.length();
281 if (e==uri.length())
282 return true;
283 char c = uri.charAt(e);
284 return c==';'||c=='#'||c=='/'||c=='?';
285 }
286
287
288
289
290
291 private static class FormCredential implements Serializable, HttpSessionBindingListener
292 {
293 String _jUserName;
294 String _jPassword;
295 transient Principal _userPrincipal;
296 transient UserRealm _realm;
297
298 void authenticate(UserRealm realm,String user,String password,Request request)
299 {
300 _jUserName=user;
301 _jPassword=password;
302 _userPrincipal = realm.authenticate(user, password, request);
303 if (_userPrincipal!=null)
304 _realm=realm;
305 else
306 {
307 Log.warn("AUTH FAILURE: user {}",StringUtil.printable(user));
308 request.setUserPrincipal(null);
309 }
310 }
311
312 void authenticate(UserRealm realm,Request request)
313 {
314 _userPrincipal = realm.authenticate(_jUserName, _jPassword, request);
315 if (_userPrincipal!=null)
316 _realm=realm;
317 else
318 {
319 Log.warn("AUTH FAILURE: user {}",StringUtil.printable(_jUserName));
320 request.setUserPrincipal(null);
321 }
322 }
323
324
325 public void valueBound(HttpSessionBindingEvent event) {}
326
327 public void valueUnbound(HttpSessionBindingEvent event)
328 {
329 if(Log.isDebugEnabled())Log.debug("Logout "+_jUserName);
330
331 if(_realm instanceof SSORealm)
332 ((SSORealm)_realm).clearSingleSignOn(_jUserName);
333
334 if(_realm!=null && _userPrincipal!=null)
335 _realm.logout(_userPrincipal);
336 }
337
338 public int hashCode()
339 {
340 return _jUserName.hashCode()+_jPassword.hashCode();
341 }
342
343 public boolean equals(Object o)
344 {
345 if (!(o instanceof FormCredential))
346 return false;
347 FormCredential fc = (FormCredential)o;
348 return
349 _jUserName.equals(fc._jUserName) &&
350 _jPassword.equals(fc._jPassword);
351 }
352
353 public String toString()
354 {
355 return "Cred["+_jUserName+"]";
356 }
357
358 }
359 }