1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.security;
15
16 import java.io.IOException;
17 import java.security.Principal;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.eclipse.jetty.server.Handler;
28 import org.eclipse.jetty.server.HttpConnection;
29 import org.eclipse.jetty.server.Request;
30 import org.eclipse.jetty.server.Response;
31 import org.eclipse.jetty.server.UserIdentity;
32 import org.eclipse.jetty.server.handler.ContextHandler;
33 import org.eclipse.jetty.server.handler.HandlerWrapper;
34 import org.eclipse.jetty.util.component.LifeCycle;
35 import org.eclipse.jetty.util.log.Log;
36
37
38
39
40
41
42
43
44
45 public abstract class SecurityHandler extends HandlerWrapper implements Authenticator.Configuration
46 {
47
48 private boolean _checkWelcomeFiles = false;
49 private Authenticator _authenticator;
50 private Authenticator.Factory _authenticatorFactory=new DefaultAuthenticatorFactory();
51 private boolean _isLazy=true;
52 private String _realmName;
53 private String _authMethod;
54 private final Map<String,String> _initParameters=new HashMap<String,String>();
55 private LoginService _loginService;
56 private boolean _loginServiceShared;
57 private IdentityService<UserIdentity,?> _identityService;
58
59
60 protected SecurityHandler()
61 {
62 }
63
64
65
66
67
68 public IdentityService<UserIdentity,?> getIdentityService()
69 {
70 return _identityService;
71 }
72
73
74
75
76
77 public void setIdentityService(IdentityService<UserIdentity,?> identityService)
78 {
79 if (isStarted())
80 throw new IllegalStateException("Started");
81 _identityService = identityService;
82 }
83
84
85
86
87
88 public LoginService getLoginService()
89 {
90 return _loginService;
91 }
92
93
94
95
96
97 public void setLoginService(LoginService loginService)
98 {
99 if (isStarted())
100 throw new IllegalStateException("Started");
101 _loginService = loginService;
102 _loginServiceShared=false;
103 }
104
105
106
107 public Authenticator getAuthenticator()
108 {
109 return _authenticator;
110 }
111
112
113
114
115
116
117 public void setAuthenticator(Authenticator authenticator)
118 {
119 if (isStarted())
120 throw new IllegalStateException("Started");
121 _authenticator = authenticator;
122 }
123
124
125
126
127
128 public Authenticator.Factory getAuthenticatorFactory()
129 {
130 return _authenticatorFactory;
131 }
132
133
134
135
136
137
138 public void setAuthenticatorFactory(Authenticator.Factory authenticatorFactory)
139 {
140 if (isRunning())
141 throw new IllegalStateException("running");
142 _authenticatorFactory = authenticatorFactory;
143 }
144
145
146
147
148
149 public boolean isLazy()
150 {
151 return _isLazy;
152 }
153
154
155
156
157
158
159 public void setLazy(boolean isLazy)
160 {
161 if (isRunning())
162 throw new IllegalStateException("running");
163 _isLazy = isLazy;
164 }
165
166
167
168
169
170 public String getRealmName()
171 {
172 return _realmName;
173 }
174
175
176
177
178
179
180 public void setRealmName(String realmName)
181 {
182 if (isRunning())
183 throw new IllegalStateException("running");
184 _realmName = realmName;
185 }
186
187
188
189
190
191 public String getAuthMethod()
192 {
193 return _authMethod;
194 }
195
196
197
198
199
200
201 public void setAuthMethod(String authMethod)
202 {
203 if (isRunning())
204 throw new IllegalStateException("running");
205 _authMethod = authMethod;
206 }
207
208
209
210
211
212 public boolean isCheckWelcomeFiles()
213 {
214 return _checkWelcomeFiles;
215 }
216
217
218
219
220
221
222
223 public void setCheckWelcomeFiles(boolean authenticateWelcomeFiles)
224 {
225 if (isRunning())
226 throw new IllegalStateException("running");
227 _checkWelcomeFiles = authenticateWelcomeFiles;
228 }
229
230
231 public String getInitParameter(String key)
232 {
233 return _initParameters.get(key);
234 }
235
236
237 public Set<String> getInitParameterNames()
238 {
239 return _initParameters.keySet();
240 }
241
242
243
244
245
246
247
248
249 public String setInitParameter(String key, String value)
250 {
251 if (isRunning())
252 throw new IllegalStateException("running");
253 return _initParameters.put(key,value);
254 }
255
256
257
258 protected LoginService findLoginService()
259 {
260 List<LoginService> list = getServer().getBeans(LoginService.class);
261
262 for (LoginService service : list)
263 if (service.getName()!=null && service.getName().equals(getRealmName()))
264 return service;
265 if (list.size()>0)
266 return list.get(0);
267 return null;
268 }
269
270
271 protected IdentityService<UserIdentity,?> findIdentityService()
272 {
273 List<IdentityService> services = getServer().getBeans(IdentityService.class);
274 if (services!=null && services.size()>0)
275 return services.get(0);
276 return null;
277 }
278
279
280
281
282 protected void doStart()
283 throws Exception
284 {
285
286
287
288 if (_loginService==null)
289 {
290 _loginService=findLoginService();
291 if (_loginService!=null)
292 _loginServiceShared=true;
293 }
294
295 if (_identityService==null)
296 {
297 if (_loginService!=null)
298 _identityService=_loginService.getIdentityService();
299
300 if (_identityService==null)
301 _identityService=findIdentityService();
302
303 if (_identityService==null)
304 _identityService=new DefaultIdentityService();
305 }
306
307 if (_loginService!=null)
308 {
309 if (_loginService.getIdentityService()==null)
310 _loginService.setIdentityService(_identityService);
311 else if (_loginService.getIdentityService()!=_identityService)
312 throw new IllegalStateException("LoginService has different IdentityService to "+this);
313 }
314
315 if (!_loginServiceShared && _loginService instanceof LifeCycle)
316 ((LifeCycle)_loginService).start();
317
318 if (_authenticator==null && _authenticatorFactory!=null)
319 {
320 _authenticator=_authenticatorFactory.getAuthenticator(getServer(),ContextHandler.getCurrentContext(),this);
321 if (_authenticator!=null)
322 _authMethod=_authenticator.getAuthMethod();
323 }
324
325 if (_authenticator==null)
326 {
327 Log.warn("No ServerAuthentication for "+this);
328 throw new IllegalStateException("No ServerAuthentication");
329 }
330
331 _authenticator.setConfiguration(this);
332 if (_authenticator instanceof LifeCycle)
333 ((LifeCycle)_authenticator).start();
334
335
336 super.doStart();
337 }
338
339
340
341
342
343 @Override
344 protected void doStop() throws Exception
345 {
346 super.doStop();
347
348 if (!_loginServiceShared && _loginService instanceof LifeCycle)
349 ((LifeCycle)_loginService).stop();
350
351 }
352
353 protected boolean checkSecurity(Request request)
354 {
355 switch(request.getDispatcherType())
356 {
357 case REQUEST:
358 case ASYNC:
359 return true;
360 case FORWARD:
361 if (_checkWelcomeFiles && request.getAttribute("org.eclipse.jetty.server.welcome") != null)
362 {
363 request.removeAttribute("org.eclipse.jetty.server.welcome");
364 return true;
365 }
366 return false;
367 default:
368 return false;
369 }
370 }
371
372
373
374
375
376
377
378 public void handle(String pathInContext, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
379 {
380 final Request base_request = (request instanceof Request) ? (Request) request : HttpConnection.getCurrentConnection().getRequest();
381 final Response base_response = (response instanceof Response) ? (Response) response : HttpConnection.getCurrentConnection().getResponse();
382 final Handler handler=getHandler();
383
384 if (handler==null)
385 return;
386
387 if (checkSecurity(base_request))
388 {
389 Object constraintInfo = prepareConstraintInfo(pathInContext, base_request);
390
391
392 if (!checkUserDataPermissions(pathInContext, base_request, base_response, constraintInfo))
393 {
394 if (!base_request.isHandled())
395 {
396 response.sendError(Response.SC_FORBIDDEN);
397 base_request.setHandled(true);
398 }
399 return;
400 }
401
402
403 boolean isAuthMandatory = isAuthMandatory(base_request, base_response, constraintInfo);
404
405
406 UserIdentity old_user_identity=base_request.getUserIdentity();
407 try
408 {
409 final Authenticator authenticator = _authenticator;
410 Authentication authentication = authenticator.validateRequest(request, response, isAuthMandatory);
411
412 if (authentication.getAuthStatus() == Authentication.Status.SUCCESS)
413 {
414 final UserIdentity user_identity=authentication.getUserIdentity();
415 base_request.setAuthType(authentication.getAuthMethod());
416 base_request.setUserIdentity(user_identity);
417
418 if (isAuthMandatory && !checkWebResourcePermissions(pathInContext, base_request, base_response, constraintInfo, user_identity))
419 {
420 response.sendError(Response.SC_FORBIDDEN, "User not in required role");
421 base_request.setHandled(true);
422 return;
423 }
424
425 handler.handle(pathInContext, request, response);
426
427 authenticator.secureResponse(request, response, isAuthMandatory, authentication);
428 }
429 else
430 {
431 base_request.setHandled(true);
432 }
433 }
434 catch (ServerAuthException e)
435 {
436
437
438 response.sendError(Response.SC_INTERNAL_SERVER_ERROR, e.getMessage());
439 }
440 finally
441 {
442 base_request.setUserIdentity(old_user_identity);
443 }
444 }
445 else
446 handler.handle(pathInContext, request, response);
447 }
448
449
450
451 protected abstract Object prepareConstraintInfo(String pathInContext, Request request);
452
453
454 protected abstract boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException;
455
456
457 protected abstract boolean isAuthMandatory(Request base_request, Response base_response, Object constraintInfo);
458
459
460 protected abstract boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo,
461 UserIdentity userIdentity) throws IOException;
462
463
464
465
466 public class NotChecked implements Principal
467 {
468 public String getName()
469 {
470 return null;
471 }
472
473 public String toString()
474 {
475 return "NOT CHECKED";
476 }
477
478 public SecurityHandler getSecurityHandler()
479 {
480 return SecurityHandler.this;
481 }
482 }
483
484
485
486
487 public static Principal __NO_USER = new Principal()
488 {
489 public String getName()
490 {
491 return null;
492 }
493
494 public String toString()
495 {
496 return "No User";
497 }
498 };
499
500
501
502
503
504
505
506
507
508
509
510 public static Principal __NOBODY = new Principal()
511 {
512 public String getName()
513 {
514 return "Nobody";
515 }
516
517 public String toString()
518 {
519 return getName();
520 }
521 };
522
523
524 }