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