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