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.Authenticator;
28 import org.mortbay.jetty.Request;
29 import org.mortbay.jetty.Response;
30 import org.mortbay.jetty.UserRealm;
31 import org.mortbay.log.Log;
32 import org.mortbay.util.StringUtil;
33 import org.mortbay.util.URIUtil;
34
35
36
37
38
39
40
41
42
43
44
45 public class FormAuthenticator implements Authenticator
46 {
47
48 public final static String __J_URI="org.mortbay.jetty.URI";
49 public final static String __J_AUTHENTICATED="org.mortbay.jetty.Auth";
50 public final static String __J_SECURITY_CHECK="/j_security_check";
51 public final static String __J_USERNAME="j_username";
52 public final static String __J_PASSWORD="j_password";
53
54 private String _formErrorPage;
55 private String _formErrorPath;
56 private String _formLoginPage;
57 private String _formLoginPath;
58
59
60 public String getAuthMethod()
61 {
62 return HttpServletRequest.FORM_AUTH;
63 }
64
65
66 public void setLoginPage(String path)
67 {
68 if (!path.startsWith("/"))
69 {
70 Log.warn("form-login-page must start with /");
71 path="/"+path;
72 }
73 _formLoginPage=path;
74 _formLoginPath=path;
75 if (_formLoginPath.indexOf('?')>0)
76 _formLoginPath=_formLoginPath.substring(0,_formLoginPath.indexOf('?'));
77 }
78
79
80 public String getLoginPage()
81 {
82 return _formLoginPage;
83 }
84
85
86 public void setErrorPage(String path)
87 {
88 if (path==null || path.trim().length()==0)
89 {
90 _formErrorPath=null;
91 _formErrorPage=null;
92 }
93 else
94 {
95 if (!path.startsWith("/"))
96 {
97 Log.warn("form-error-page must start with /");
98 path="/"+path;
99 }
100 _formErrorPage=path;
101 _formErrorPath=path;
102
103 if (_formErrorPath!=null && _formErrorPath.indexOf('?')>0)
104 _formErrorPath=_formErrorPath.substring(0,_formErrorPath.indexOf('?'));
105 }
106 }
107
108
109 public String getErrorPage()
110 {
111 return _formErrorPage;
112 }
113
114
115
116
117
118
119 public Principal authenticate(UserRealm realm,
120 String pathInContext,
121 Request request,
122 Response response)
123 throws IOException
124 {
125
126 String uri = pathInContext;
127
128
129 HttpSession session=request.getSession(response!=null);
130 if (session==null)
131 return null;
132
133
134
135 if ( uri.endsWith(__J_SECURITY_CHECK) )
136 {
137
138 FormCredential form_cred=new FormCredential();
139 form_cred.authenticate(realm,
140 request.getParameter(__J_USERNAME),
141 request.getParameter(__J_PASSWORD),
142 request);
143
144 String nuri=(String)session.getAttribute(__J_URI);
145 if (nuri==null || nuri.length()==0)
146 {
147 nuri=request.getContextPath();
148 if (nuri.length()==0)
149 nuri=URIUtil.SLASH;
150 }
151
152 if (form_cred._userPrincipal!=null)
153 {
154
155 if(Log.isDebugEnabled())Log.debug("Form authentication OK for "+form_cred._jUserName);
156 session.removeAttribute(__J_URI);
157 request.setAuthType(Constraint.__FORM_AUTH);
158 request.setUserPrincipal(form_cred._userPrincipal);
159 session.setAttribute(__J_AUTHENTICATED,form_cred);
160
161
162 if (realm instanceof SSORealm)
163 ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new Password(form_cred._jPassword));
164
165
166 if (response != null) {
167 response.setContentLength(0);
168 response.sendRedirect(response.encodeRedirectURL(nuri));
169 }
170 }
171 else
172 {
173 if(Log.isDebugEnabled())Log.debug("Form authentication FAILED for "+StringUtil.printable(form_cred._jUserName));
174 if (_formErrorPage==null)
175 {
176 if (response != null)
177 response.sendError(HttpServletResponse.SC_FORBIDDEN);
178 }
179 else
180 {
181 if (response != null)
182 response.setContentLength(0);
183 response.sendRedirect(response.encodeRedirectURL
184 (URIUtil.addPaths(request.getContextPath(),
185 _formErrorPage)));
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 UserRealm.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 public boolean isLoginOrErrorPage(String pathInContext)
267 {
268 return pathInContext!=null &&
269 (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
270 }
271
272
273
274
275 private static class FormCredential implements Serializable, HttpSessionBindingListener
276 {
277 String _jUserName;
278 String _jPassword;
279 transient Principal _userPrincipal;
280 transient UserRealm _realm;
281
282 void authenticate(UserRealm realm,String user,String password,Request request)
283 {
284 _jUserName=user;
285 _jPassword=password;
286 _userPrincipal = realm.authenticate(user, password, request);
287 if (_userPrincipal!=null)
288 _realm=realm;
289 else
290 {
291 Log.warn("AUTH FAILURE: user {}",StringUtil.printable(user));
292 request.setUserPrincipal(null);
293 }
294 }
295
296 void authenticate(UserRealm realm,Request request)
297 {
298 _userPrincipal = realm.authenticate(_jUserName, _jPassword, request);
299 if (_userPrincipal!=null)
300 _realm=realm;
301 else
302 {
303 Log.warn("AUTH FAILURE: user {}",StringUtil.printable(_jUserName));
304 request.setUserPrincipal(null);
305 }
306 }
307
308
309 public void valueBound(HttpSessionBindingEvent event) {}
310
311 public void valueUnbound(HttpSessionBindingEvent event)
312 {
313 if(Log.isDebugEnabled())Log.debug("Logout "+_jUserName);
314
315 if(_realm instanceof SSORealm)
316 ((SSORealm)_realm).clearSingleSignOn(_jUserName);
317
318 if(_realm!=null && _userPrincipal!=null)
319 _realm.logout(_userPrincipal);
320 }
321
322 public int hashCode()
323 {
324 return _jUserName.hashCode()+_jPassword.hashCode();
325 }
326
327 public boolean equals(Object o)
328 {
329 if (!(o instanceof FormCredential))
330 return false;
331 FormCredential fc = (FormCredential)o;
332 return
333 _jUserName.equals(fc._jUserName) &&
334 _jPassword.equals(fc._jPassword);
335 }
336
337 public String toString()
338 {
339 return "Cred["+_jUserName+"]";
340 }
341
342 }
343 }