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.Enumeration;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23
24 import javax.servlet.ServletException;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
28 import org.eclipse.jetty.security.authentication.DeferredAuthentication;
29 import org.eclipse.jetty.server.Authentication;
30 import org.eclipse.jetty.server.Handler;
31 import org.eclipse.jetty.server.Request;
32 import org.eclipse.jetty.server.Response;
33 import org.eclipse.jetty.server.UserIdentity;
34 import org.eclipse.jetty.server.handler.ContextHandler;
35 import org.eclipse.jetty.server.handler.ContextHandler.Context;
36 import org.eclipse.jetty.server.handler.HandlerWrapper;
37 import org.eclipse.jetty.util.component.LifeCycle;
38 import org.eclipse.jetty.util.log.Log;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public abstract class SecurityHandler extends HandlerWrapper implements Authenticator.AuthConfiguration
55 {
56
57 private boolean _checkWelcomeFiles = false;
58 private Authenticator _authenticator;
59 private Authenticator.Factory _authenticatorFactory=new DefaultAuthenticatorFactory();
60 private String _realmName;
61 private String _authMethod;
62 private final Map<String,String> _initParameters=new HashMap<String,String>();
63 private LoginService _loginService;
64 private boolean _loginServiceShared;
65 private IdentityService _identityService;
66 private boolean _renewSession=true;
67
68
69 protected SecurityHandler()
70 {
71 }
72
73
74
75
76
77 public IdentityService getIdentityService()
78 {
79 return _identityService;
80 }
81
82
83
84
85
86 public void setIdentityService(IdentityService identityService)
87 {
88 if (isStarted())
89 throw new IllegalStateException("Started");
90 _identityService = identityService;
91 }
92
93
94
95
96
97 public LoginService getLoginService()
98 {
99 return _loginService;
100 }
101
102
103
104
105
106 public void setLoginService(LoginService loginService)
107 {
108 if (isStarted())
109 throw new IllegalStateException("Started");
110 _loginService = loginService;
111 _loginServiceShared=false;
112 }
113
114
115
116 public Authenticator getAuthenticator()
117 {
118 return _authenticator;
119 }
120
121
122
123
124
125
126 public void setAuthenticator(Authenticator authenticator)
127 {
128 if (isStarted())
129 throw new IllegalStateException("Started");
130 _authenticator = authenticator;
131 }
132
133
134
135
136
137 public Authenticator.Factory getAuthenticatorFactory()
138 {
139 return _authenticatorFactory;
140 }
141
142
143
144
145
146
147 public void setAuthenticatorFactory(Authenticator.Factory authenticatorFactory)
148 {
149 if (isRunning())
150 throw new IllegalStateException("running");
151 _authenticatorFactory = authenticatorFactory;
152 }
153
154
155
156
157
158 public String getRealmName()
159 {
160 return _realmName;
161 }
162
163
164
165
166
167
168 public void setRealmName(String realmName)
169 {
170 if (isRunning())
171 throw new IllegalStateException("running");
172 _realmName = realmName;
173 }
174
175
176
177
178
179 public String getAuthMethod()
180 {
181 return _authMethod;
182 }
183
184
185
186
187
188
189 public void setAuthMethod(String authMethod)
190 {
191 if (isRunning())
192 throw new IllegalStateException("running");
193 _authMethod = authMethod;
194 }
195
196
197
198
199
200 public boolean isCheckWelcomeFiles()
201 {
202 return _checkWelcomeFiles;
203 }
204
205
206
207
208
209
210
211 public void setCheckWelcomeFiles(boolean authenticateWelcomeFiles)
212 {
213 if (isRunning())
214 throw new IllegalStateException("running");
215 _checkWelcomeFiles = authenticateWelcomeFiles;
216 }
217
218
219 public String getInitParameter(String key)
220 {
221 return _initParameters.get(key);
222 }
223
224
225 public Set<String> getInitParameterNames()
226 {
227 return _initParameters.keySet();
228 }
229
230
231
232
233
234
235
236
237 public String setInitParameter(String key, String value)
238 {
239 if (isRunning())
240 throw new IllegalStateException("running");
241 return _initParameters.put(key,value);
242 }
243
244
245
246 protected LoginService findLoginService()
247 {
248 List<LoginService> list = getServer().getBeans(LoginService.class);
249
250 for (LoginService service : list)
251 if (service.getName()!=null && service.getName().equals(getRealmName()))
252 return service;
253 if (list.size()>0)
254 return list.get(0);
255 return null;
256 }
257
258
259 protected IdentityService findIdentityService()
260 {
261 return getServer().getBean(IdentityService.class);
262 }
263
264
265
266
267 @Override
268 protected void doStart()
269 throws Exception
270 {
271
272 ContextHandler.Context context =ContextHandler.getCurrentContext();
273 if (context!=null)
274 {
275 Enumeration<String> names=context.getInitParameterNames();
276 while (names!=null && names.hasMoreElements())
277 {
278 String name =names.nextElement();
279 if (name.startsWith("org.eclipse.jetty.security.") &&
280 getInitParameter(name)==null)
281 setInitParameter(name,context.getInitParameter(name));
282 }
283 }
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 && _realmName!=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 && _identityService!=null)
319 {
320 _authenticator=_authenticatorFactory.getAuthenticator(getServer(),ContextHandler.getCurrentContext(),this, _identityService, _loginService);
321 if (_authenticator!=null)
322 _authMethod=_authenticator.getAuthMethod();
323 }
324
325 if (_authenticator==null)
326 {
327 if (_realmName!=null)
328 {
329 Log.warn("No ServerAuthentication for "+this);
330 throw new IllegalStateException("No ServerAuthentication");
331 }
332 }
333 else
334 {
335 _authenticator.setConfiguration(this);
336 if (_authenticator instanceof LifeCycle)
337 ((LifeCycle)_authenticator).start();
338 }
339
340 super.doStart();
341 }
342
343
344
345
346
347 @Override
348 protected void doStop() throws Exception
349 {
350 super.doStop();
351
352 if (!_loginServiceShared && _loginService instanceof LifeCycle)
353 ((LifeCycle)_loginService).stop();
354
355 }
356
357
358 protected boolean checkSecurity(Request request)
359 {
360 switch(request.getDispatcherType())
361 {
362 case REQUEST:
363 case ASYNC:
364 return true;
365 case FORWARD:
366 if (_checkWelcomeFiles && request.getAttribute("org.eclipse.jetty.server.welcome") != null)
367 {
368 request.removeAttribute("org.eclipse.jetty.server.welcome");
369 return true;
370 }
371 return false;
372 default:
373 return false;
374 }
375 }
376
377
378
379
380
381 public boolean isSessionRenewedOnAuthentication()
382 {
383 return _renewSession;
384 }
385
386
387
388
389
390
391
392 public void setSessionRenewedOnAuthentication(boolean renew)
393 {
394 _renewSession=renew;
395 }
396
397
398
399
400
401
402
403 @Override
404 public void handle(String pathInContext, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
405 {
406 final Response base_response = baseRequest.getResponse();
407 final Handler handler=getHandler();
408
409 if (handler==null)
410 return;
411
412 final Authenticator authenticator = _authenticator;
413
414 if (authenticator!=null && checkSecurity(baseRequest))
415 {
416 Object constraintInfo = prepareConstraintInfo(pathInContext, baseRequest);
417
418
419 if (!checkUserDataPermissions(pathInContext, baseRequest, base_response, constraintInfo))
420 {
421 if (!baseRequest.isHandled())
422 {
423 response.sendError(Response.SC_FORBIDDEN);
424 baseRequest.setHandled(true);
425 }
426 return;
427 }
428
429
430 boolean isAuthMandatory =
431 isAuthMandatory(baseRequest, base_response, constraintInfo);
432
433
434 Object previousIdentity = null;
435 try
436 {
437 Authentication authentication = baseRequest.getAuthentication();
438 if (authentication==null || authentication==Authentication.NOT_CHECKED)
439 authentication=authenticator.validateRequest(request, response, isAuthMandatory);
440
441 if (authentication instanceof Authentication.Wrapped)
442 {
443 request=((Authentication.Wrapped)authentication).getHttpServletRequest();
444 response=((Authentication.Wrapped)authentication).getHttpServletResponse();
445 }
446
447 if (authentication instanceof Authentication.ResponseSent)
448 {
449 baseRequest.setHandled(true);
450 }
451 else if (authentication instanceof Authentication.User)
452 {
453 Authentication.User userAuth = (Authentication.User)authentication;
454 baseRequest.setAuthentication(authentication);
455 previousIdentity = _identityService.associate(userAuth.getUserIdentity());
456
457 if (isAuthMandatory)
458 {
459 boolean authorized=checkWebResourcePermissions(pathInContext, baseRequest, base_response, constraintInfo, userAuth.getUserIdentity());
460 if (!authorized)
461 {
462 response.sendError(Response.SC_FORBIDDEN, "!role");
463 baseRequest.setHandled(true);
464 return;
465 }
466 }
467
468 handler.handle(pathInContext, baseRequest, request, response);
469 authenticator.secureResponse(request, response, isAuthMandatory, userAuth);
470 }
471 else if (authentication instanceof Authentication.Deferred)
472 {
473 DeferredAuthentication deferred= (DeferredAuthentication)authentication;
474 deferred.setIdentityService(_identityService);
475 deferred.setLoginService(_loginService);
476 baseRequest.setAuthentication(authentication);
477
478 try
479 {
480 handler.handle(pathInContext, baseRequest, request, response);
481 }
482 finally
483 {
484 previousIdentity = deferred.getPreviousAssociation();
485 deferred.setIdentityService(null);
486 }
487
488 Authentication auth=baseRequest.getAuthentication();
489 if (auth instanceof Authentication.User)
490 {
491 Authentication.User userAuth = (Authentication.User)auth;
492 authenticator.secureResponse(request, response, isAuthMandatory, userAuth);
493 }
494 else
495 authenticator.secureResponse(request, response, isAuthMandatory, null);
496 }
497 else
498 {
499 baseRequest.setAuthentication(authentication);
500 previousIdentity = _identityService.associate(null);
501 handler.handle(pathInContext, baseRequest, request, response);
502 authenticator.secureResponse(request, response, isAuthMandatory, null);
503 }
504 }
505 catch (ServerAuthException e)
506 {
507
508
509 response.sendError(Response.SC_INTERNAL_SERVER_ERROR, e.getMessage());
510 }
511 finally
512 {
513 _identityService.disassociate(previousIdentity);
514 }
515 }
516 else
517 handler.handle(pathInContext, baseRequest, request, response);
518 }
519
520
521
522 public static SecurityHandler getCurrentSecurityHandler()
523 {
524 Context context = ContextHandler.getCurrentContext();
525 if (context==null)
526 return null;
527
528 SecurityHandler security = context.getContextHandler().getChildHandlerByClass(SecurityHandler.class);
529 return security;
530 }
531
532
533 public void logout(Authentication.User user)
534 {
535 Log.debug("logout {}",user);
536 LoginService login_service=getLoginService();
537 if (login_service!=null)
538 {
539 login_service.logout(user.getUserIdentity());
540 }
541
542 IdentityService identity_service=getIdentityService();
543 if (identity_service!=null)
544 {
545
546 Object previous=null;
547 identity_service.disassociate(previous);
548 }
549 }
550
551
552 protected abstract Object prepareConstraintInfo(String pathInContext, Request request);
553
554
555 protected abstract boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException;
556
557
558 protected abstract boolean isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo);
559
560
561 protected abstract boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo,
562 UserIdentity userIdentity) throws IOException;
563
564
565
566
567 public class NotChecked implements Principal
568 {
569 public String getName()
570 {
571 return null;
572 }
573
574 @Override
575 public String toString()
576 {
577 return "NOT CHECKED";
578 }
579
580 public SecurityHandler getSecurityHandler()
581 {
582 return SecurityHandler.this;
583 }
584 }
585
586
587
588
589 public static Principal __NO_USER = new Principal()
590 {
591 public String getName()
592 {
593 return null;
594 }
595
596 @Override
597 public String toString()
598 {
599 return "No User";
600 }
601 };
602
603
604
605
606
607
608
609
610
611
612
613 public static Principal __NOBODY = new Principal()
614 {
615 public String getName()
616 {
617 return "Nobody";
618 }
619
620 @Override
621 public String toString()
622 {
623 return getName();
624 }
625 };
626
627 }