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
249 protected LoginService findLoginService()
250 {
251 List<LoginService> list = getServer().getBeans(LoginService.class);
252
253 for (LoginService service : list)
254 if (service.getName()!=null && service.getName().equals(getRealmName()))
255 return service;
256 if (list.size()>0)
257 return list.get(0);
258 return null;
259 }
260
261
262 protected IdentityService findIdentityService()
263 {
264 return getServer().getBean(IdentityService.class);
265 }
266
267
268
269
270 @Override
271 protected void doStart()
272 throws Exception
273 {
274
275 ContextHandler.Context context =ContextHandler.getCurrentContext();
276 if (context!=null)
277 {
278 Enumeration<String> names=context.getInitParameterNames();
279 while (names!=null && names.hasMoreElements())
280 {
281 String name =names.nextElement();
282 if (name.startsWith("org.eclipse.jetty.security.") &&
283 getInitParameter(name)==null)
284 setInitParameter(name,context.getInitParameter(name));
285 }
286 }
287
288
289
290
291 if (_loginService==null)
292 {
293 _loginService=findLoginService();
294 if (_loginService!=null)
295 _loginServiceShared=true;
296 }
297
298 if (_identityService==null)
299 {
300 if (_loginService!=null)
301 _identityService=_loginService.getIdentityService();
302
303 if (_identityService==null)
304 _identityService=findIdentityService();
305
306 if (_identityService==null && _realmName!=null)
307 _identityService=new DefaultIdentityService();
308 }
309
310 if (_loginService!=null)
311 {
312 if (_loginService.getIdentityService()==null)
313 _loginService.setIdentityService(_identityService);
314 else if (_loginService.getIdentityService()!=_identityService)
315 throw new IllegalStateException("LoginService has different IdentityService to "+this);
316 }
317
318 if (!_loginServiceShared && _loginService instanceof LifeCycle)
319 ((LifeCycle)_loginService).start();
320
321 System.err.println("authenticator="+_authenticator+" authenticatorFactory="+_authenticatorFactory+" identityService="+_identityService);
322 if (_authenticator==null && _authenticatorFactory!=null && _identityService!=null)
323 {
324 _authenticator=_authenticatorFactory.getAuthenticator(getServer(),ContextHandler.getCurrentContext(),this, _identityService, _loginService);
325 if (_authenticator!=null)
326 _authMethod=_authenticator.getAuthMethod();
327 System.err.println("Called auth factory, authenticator="+_authenticator);
328 }
329
330 if (_authenticator==null)
331 {
332 if (_realmName!=null)
333 {
334 LOG.warn("No ServerAuthentication for "+this);
335 throw new IllegalStateException("No ServerAuthentication");
336 }
337 }
338 else
339 {
340 _authenticator.setConfiguration(this);
341 if (_authenticator instanceof LifeCycle)
342 ((LifeCycle)_authenticator).start();
343 }
344
345 super.doStart();
346 }
347
348
349
350
351
352 @Override
353 protected void doStop() throws Exception
354 {
355 super.doStop();
356
357 if (!_loginServiceShared && _loginService instanceof LifeCycle)
358 ((LifeCycle)_loginService).stop();
359
360 }
361
362
363 protected boolean checkSecurity(Request request)
364 {
365 switch(request.getDispatcherType())
366 {
367 case REQUEST:
368 case ASYNC:
369 return true;
370 case FORWARD:
371 if (_checkWelcomeFiles && request.getAttribute("org.eclipse.jetty.server.welcome") != null)
372 {
373 request.removeAttribute("org.eclipse.jetty.server.welcome");
374 return true;
375 }
376 return false;
377 default:
378 return false;
379 }
380 }
381
382
383
384
385
386 public boolean isSessionRenewedOnAuthentication()
387 {
388 return _renewSession;
389 }
390
391
392
393
394
395
396
397 public void setSessionRenewedOnAuthentication(boolean renew)
398 {
399 _renewSession=renew;
400 }
401
402
403
404
405
406
407
408 @Override
409 public void handle(String pathInContext, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
410 {
411 final Response base_response = baseRequest.getResponse();
412 final Handler handler=getHandler();
413
414 if (handler==null)
415 return;
416
417 final Authenticator authenticator = _authenticator;
418
419 if (authenticator!=null && checkSecurity(baseRequest))
420 {
421 Object constraintInfo = prepareConstraintInfo(pathInContext, baseRequest);
422
423
424 if (!checkUserDataPermissions(pathInContext, baseRequest, base_response, constraintInfo))
425 {
426 if (!baseRequest.isHandled())
427 {
428 response.sendError(Response.SC_FORBIDDEN);
429 baseRequest.setHandled(true);
430 }
431 return;
432 }
433
434
435 boolean isAuthMandatory =
436 isAuthMandatory(baseRequest, base_response, constraintInfo);
437
438
439 Object previousIdentity = null;
440 try
441 {
442 Authentication authentication = baseRequest.getAuthentication();
443 if (authentication==null || authentication==Authentication.NOT_CHECKED)
444 authentication=authenticator.validateRequest(request, response, isAuthMandatory);
445
446 if (authentication instanceof Authentication.Wrapped)
447 {
448 request=((Authentication.Wrapped)authentication).getHttpServletRequest();
449 response=((Authentication.Wrapped)authentication).getHttpServletResponse();
450 }
451
452 if (authentication instanceof Authentication.ResponseSent)
453 {
454 baseRequest.setHandled(true);
455 }
456 else if (authentication instanceof Authentication.User)
457 {
458 Authentication.User userAuth = (Authentication.User)authentication;
459 baseRequest.setAuthentication(authentication);
460 previousIdentity = _identityService.associate(userAuth.getUserIdentity());
461
462 if (isAuthMandatory)
463 {
464 boolean authorized=checkWebResourcePermissions(pathInContext, baseRequest, base_response, constraintInfo, userAuth.getUserIdentity());
465 if (!authorized)
466 {
467 response.sendError(Response.SC_FORBIDDEN, "!role");
468 baseRequest.setHandled(true);
469 return;
470 }
471 }
472
473 handler.handle(pathInContext, baseRequest, request, response);
474 authenticator.secureResponse(request, response, isAuthMandatory, userAuth);
475 }
476 else if (authentication instanceof Authentication.Deferred)
477 {
478 DeferredAuthentication deferred= (DeferredAuthentication)authentication;
479 deferred.setIdentityService(_identityService);
480 deferred.setLoginService(_loginService);
481 baseRequest.setAuthentication(authentication);
482 System.err.println("uri="+baseRequest.getUri()+" Auth is deferred");
483 try
484 {
485 handler.handle(pathInContext, baseRequest, request, response);
486 }
487 finally
488 {
489 previousIdentity = deferred.getPreviousAssociation();
490 deferred.setIdentityService(null);
491 }
492 System.err.println("Securityhandler calling secureResponse, for Authentication.User");
493 Authentication auth=baseRequest.getAuthentication();
494 if (auth instanceof Authentication.User)
495 {
496 Authentication.User userAuth = (Authentication.User)auth;
497 authenticator.secureResponse(request, response, isAuthMandatory, userAuth);
498 }
499 else
500 authenticator.secureResponse(request, response, isAuthMandatory, null);
501 }
502 else
503 {
504 baseRequest.setAuthentication(authentication);
505 previousIdentity = _identityService.associate(null);
506 handler.handle(pathInContext, baseRequest, request, response);
507 authenticator.secureResponse(request, response, isAuthMandatory, null);
508 }
509 }
510 catch (ServerAuthException e)
511 {
512
513
514 response.sendError(Response.SC_INTERNAL_SERVER_ERROR, e.getMessage());
515 }
516 finally
517 {
518 _identityService.disassociate(previousIdentity);
519 }
520 }
521 else
522 handler.handle(pathInContext, baseRequest, request, response);
523 }
524
525
526
527 public static SecurityHandler getCurrentSecurityHandler()
528 {
529 Context context = ContextHandler.getCurrentContext();
530 if (context==null)
531 return null;
532
533 SecurityHandler security = context.getContextHandler().getChildHandlerByClass(SecurityHandler.class);
534 return security;
535 }
536
537
538 public void logout(Authentication.User user)
539 {
540 LOG.debug("logout {}",user);
541 LoginService login_service=getLoginService();
542 if (login_service!=null)
543 {
544 login_service.logout(user.getUserIdentity());
545 }
546
547 IdentityService identity_service=getIdentityService();
548 if (identity_service!=null)
549 {
550
551 Object previous=null;
552 identity_service.disassociate(previous);
553 }
554 }
555
556
557 protected abstract Object prepareConstraintInfo(String pathInContext, Request request);
558
559
560 protected abstract boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException;
561
562
563 protected abstract boolean isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo);
564
565
566 protected abstract boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo,
567 UserIdentity userIdentity) throws IOException;
568
569
570
571
572 public class NotChecked implements Principal
573 {
574 public String getName()
575 {
576 return null;
577 }
578
579 @Override
580 public String toString()
581 {
582 return "NOT CHECKED";
583 }
584
585 public SecurityHandler getSecurityHandler()
586 {
587 return SecurityHandler.this;
588 }
589 }
590
591
592
593
594 public static Principal __NO_USER = new Principal()
595 {
596 public String getName()
597 {
598 return null;
599 }
600
601 @Override
602 public String toString()
603 {
604 return "No User";
605 }
606 };
607
608
609
610
611
612
613
614
615
616
617
618 public static Principal __NOBODY = new Principal()
619 {
620 public String getName()
621 {
622 return "Nobody";
623 }
624
625 @Override
626 public String toString()
627 {
628 return getName();
629 }
630 };
631
632 }