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
133 if ( uri.endsWith(__J_SECURITY_CHECK) )
134 {
135
136 FormCredential form_cred=new FormCredential();
137 form_cred.authenticate(realm,
138 request.getParameter(__J_USERNAME),
139 request.getParameter(__J_PASSWORD),
140 request);
141
142 String nuri=(String)session.getAttribute(__J_URI);
143 if (nuri==null || nuri.length()==0)
144 {
145 nuri=request.getContextPath();
146 if (nuri.length()==0)
147 nuri=URIUtil.SLASH;
148 }
149
150 if (form_cred._userPrincipal!=null)
151 {
152
153 if(Log.isDebugEnabled())Log.debug("Form authentication OK for "+form_cred._jUserName);
154 session.removeAttribute(__J_URI);
155 request.setAuthType(Constraint.__FORM_AUTH);
156 request.setUserPrincipal(form_cred._userPrincipal);
157 session.setAttribute(__J_AUTHENTICATED,form_cred);
158
159
160 if (realm instanceof SSORealm)
161 ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new Password(form_cred._jPassword));
162
163
164 if (response != null) {
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 if (_formErrorPage==null)
173 {
174 if (response != null)
175 response.sendError(HttpServletResponse.SC_FORBIDDEN);
176 }
177 else
178 {
179 if (response != null)
180 response.setContentLength(0);
181 response.sendRedirect(response.encodeRedirectURL
182 (URIUtil.addPaths(request.getContextPath(),
183 _formErrorPage)));
184 }
185 }
186
187
188 return null;
189 }
190
191
192 FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
193
194 if (form_cred != null)
195 {
196
197 if (form_cred._userPrincipal==null)
198 {
199
200 form_cred.authenticate(realm, request);
201
202
203 if (form_cred._userPrincipal!=null && realm instanceof SSORealm)
204 ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new Password(form_cred._jPassword));
205
206 }
207 else if (!realm.reauthenticate(form_cred._userPrincipal))
208
209 form_cred._userPrincipal=null;
210
211
212 if (form_cred._userPrincipal!=null)
213 {
214 if(Log.isDebugEnabled())Log.debug("FORM Authenticated for "+form_cred._userPrincipal.getName());
215 request.setAuthType(Constraint.__FORM_AUTH);
216 request.setUserPrincipal(form_cred._userPrincipal);
217 return form_cred._userPrincipal;
218 }
219 else
220 session.setAttribute(__J_AUTHENTICATED,null);
221 }
222 else if (realm instanceof SSORealm)
223 {
224
225 Credential cred = ((SSORealm)realm).getSingleSignOn(request,response);
226
227 if (request.getUserPrincipal()!=null)
228 {
229 form_cred=new FormCredential();
230 form_cred._userPrincipal=request.getUserPrincipal();
231 form_cred._jUserName=form_cred._userPrincipal.getName();
232 if (cred!=null)
233 form_cred._jPassword=cred.toString();
234 if(Log.isDebugEnabled())Log.debug("SSO for "+form_cred._userPrincipal);
235
236 request.setAuthType(Constraint.__FORM_AUTH);
237 session.setAttribute(__J_AUTHENTICATED,form_cred);
238 return form_cred._userPrincipal;
239 }
240 }
241
242
243 if (isLoginOrErrorPage(pathInContext))
244 return SecurityHandler.__NOBODY;
245
246
247 if (response!=null)
248 {
249 if (request.getQueryString()!=null)
250 uri+="?"+request.getQueryString();
251 session.setAttribute(__J_URI,
252 request.getScheme() +
253 "://" + request.getServerName() +
254 ":" + request.getServerPort() +
255 URIUtil.addPaths(request.getContextPath(),uri));
256 response.setContentLength(0);
257 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(),
258 _formLoginPage)));
259 }
260
261 return null;
262 }
263
264 public boolean isLoginOrErrorPage(String pathInContext)
265 {
266 return pathInContext!=null &&
267 (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
268 }
269
270
271
272
273 private static class FormCredential implements Serializable, HttpSessionBindingListener
274 {
275 String _jUserName;
276 String _jPassword;
277 transient Principal _userPrincipal;
278 transient UserRealm _realm;
279
280 void authenticate(UserRealm realm,String user,String password,Request request)
281 {
282 _jUserName=user;
283 _jPassword=password;
284 _userPrincipal = realm.authenticate(user, password, request);
285 if (_userPrincipal!=null)
286 _realm=realm;
287 else
288 {
289 Log.warn("AUTH FAILURE: user {}",StringUtil.printable(user));
290 request.setUserPrincipal(null);
291 }
292 }
293
294 void authenticate(UserRealm realm,Request request)
295 {
296 _userPrincipal = realm.authenticate(_jUserName, _jPassword, request);
297 if (_userPrincipal!=null)
298 _realm=realm;
299 else
300 {
301 Log.warn("AUTH FAILURE: user {}",StringUtil.printable(_jUserName));
302 request.setUserPrincipal(null);
303 }
304 }
305
306
307 public void valueBound(HttpSessionBindingEvent event) {}
308
309 public void valueUnbound(HttpSessionBindingEvent event)
310 {
311 if(Log.isDebugEnabled())Log.debug("Logout "+_jUserName);
312
313 if(_realm instanceof SSORealm)
314 ((SSORealm)_realm).clearSingleSignOn(_jUserName);
315
316 if(_realm!=null && _userPrincipal!=null)
317 _realm.logout(_userPrincipal);
318 }
319
320 public int hashCode()
321 {
322 return _jUserName.hashCode()+_jPassword.hashCode();
323 }
324
325 public boolean equals(Object o)
326 {
327 if (!(o instanceof FormCredential))
328 return false;
329 FormCredential fc = (FormCredential)o;
330 return
331 _jUserName.equals(fc._jUserName) &&
332 _jPassword.equals(fc._jPassword);
333 }
334
335 public String toString()
336 {
337 return "Cred["+_jUserName+"]";
338 }
339
340 }
341 }