1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.security; 20 21 import java.io.IOException; 22 import java.util.ArrayList; 23 import java.util.Arrays; 24 import java.util.Collection; 25 import java.util.Collections; 26 import java.util.HashSet; 27 import java.util.List; 28 import java.util.Map; 29 import java.util.Map.Entry; 30 import java.util.Set; 31 import java.util.concurrent.CopyOnWriteArrayList; 32 import java.util.concurrent.CopyOnWriteArraySet; 33 34 import org.eclipse.jetty.http.HttpSchemes; 35 import javax.servlet.HttpConstraintElement; 36 import javax.servlet.HttpMethodConstraintElement; 37 import javax.servlet.ServletSecurityElement; 38 import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic; 39 import javax.servlet.annotation.ServletSecurity.TransportGuarantee; 40 41 import org.eclipse.jetty.http.PathMap; 42 import org.eclipse.jetty.server.AbstractHttpConnection; 43 import org.eclipse.jetty.server.Connector; 44 import org.eclipse.jetty.server.Request; 45 import org.eclipse.jetty.server.Response; 46 import org.eclipse.jetty.server.UserIdentity; 47 import org.eclipse.jetty.util.StringMap; 48 import org.eclipse.jetty.util.TypeUtil; 49 import org.eclipse.jetty.util.security.Constraint; 50 51 /* ------------------------------------------------------------ */ 52 /** 53 * Handler to enforce SecurityConstraints. This implementation is servlet spec 54 * 3.0 compliant and precomputes the constraint combinations for runtime 55 * efficiency. 56 * 57 */ 58 public class ConstraintSecurityHandler extends SecurityHandler implements ConstraintAware 59 { 60 private static final String OMISSION_SUFFIX = ".omission"; 61 62 private final List<ConstraintMapping> _constraintMappings= new CopyOnWriteArrayList<ConstraintMapping>(); 63 private final Set<String> _roles = new CopyOnWriteArraySet<String>(); 64 private final PathMap _constraintMap = new PathMap(); 65 private boolean _strict = true; 66 67 68 /* ------------------------------------------------------------ */ 69 /** 70 * @return 71 */ createConstraint()72 public static Constraint createConstraint() 73 { 74 return new Constraint(); 75 } 76 77 /* ------------------------------------------------------------ */ 78 /** 79 * @param constraint 80 * @return 81 */ createConstraint(Constraint constraint)82 public static Constraint createConstraint(Constraint constraint) 83 { 84 try 85 { 86 return (Constraint)constraint.clone(); 87 } 88 catch (CloneNotSupportedException e) 89 { 90 throw new IllegalStateException (e); 91 } 92 } 93 94 /* ------------------------------------------------------------ */ 95 /** 96 * Create a security constraint 97 * 98 * @param name 99 * @param authenticate 100 * @param roles 101 * @param dataConstraint 102 * @return 103 */ createConstraint(String name, boolean authenticate, String[] roles, int dataConstraint)104 public static Constraint createConstraint (String name, boolean authenticate, String[] roles, int dataConstraint) 105 { 106 Constraint constraint = createConstraint(); 107 if (name != null) 108 constraint.setName(name); 109 constraint.setAuthenticate(authenticate); 110 constraint.setRoles(roles); 111 constraint.setDataConstraint(dataConstraint); 112 return constraint; 113 } 114 115 116 /* ------------------------------------------------------------ */ 117 /** 118 * @param name 119 * @param element 120 * @return 121 */ createConstraint(String name, HttpConstraintElement element)122 public static Constraint createConstraint (String name, HttpConstraintElement element) 123 { 124 return createConstraint(name, element.getRolesAllowed(), element.getEmptyRoleSemantic(), element.getTransportGuarantee()); 125 } 126 127 128 /* ------------------------------------------------------------ */ 129 /** 130 * @param name 131 * @param rolesAllowed 132 * @param permitOrDeny 133 * @param transport 134 * @return 135 */ createConstraint(String name, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport)136 public static Constraint createConstraint (String name, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport) 137 { 138 Constraint constraint = createConstraint(); 139 140 if (rolesAllowed == null || rolesAllowed.length==0) 141 { 142 if (permitOrDeny.equals(EmptyRoleSemantic.DENY)) 143 { 144 //Equivalent to <auth-constraint> with no roles 145 constraint.setName(name+"-Deny"); 146 constraint.setAuthenticate(true); 147 } 148 else 149 { 150 //Equivalent to no <auth-constraint> 151 constraint.setName(name+"-Permit"); 152 constraint.setAuthenticate(false); 153 } 154 } 155 else 156 { 157 //Equivalent to <auth-constraint> with list of <security-role-name>s 158 constraint.setAuthenticate(true); 159 constraint.setRoles(rolesAllowed); 160 constraint.setName(name+"-RolesAllowed"); 161 } 162 163 //Equivalent to //<user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint> 164 constraint.setDataConstraint((transport.equals(TransportGuarantee.CONFIDENTIAL)?Constraint.DC_CONFIDENTIAL:Constraint.DC_NONE)); 165 return constraint; 166 } 167 168 169 170 /* ------------------------------------------------------------ */ 171 /** 172 * @param pathSpec 173 * @param constraintMappings 174 * @return 175 */ getConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings)176 public static List<ConstraintMapping> getConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings) 177 { 178 if (pathSpec == null || "".equals(pathSpec.trim()) || constraintMappings == null || constraintMappings.size() == 0) 179 return Collections.emptyList(); 180 181 List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>(); 182 for (ConstraintMapping mapping:constraintMappings) 183 { 184 if (pathSpec.equals(mapping.getPathSpec())) 185 { 186 mappings.add(mapping); 187 } 188 } 189 return mappings; 190 } 191 192 193 /* ------------------------------------------------------------ */ 194 /** Take out of the constraint mappings those that match the 195 * given path. 196 * 197 * @param pathSpec 198 * @param constraintMappings a new list minus the matching constraints 199 * @return 200 */ removeConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings)201 public static List<ConstraintMapping> removeConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings) 202 { 203 if (pathSpec == null || "".equals(pathSpec.trim()) || constraintMappings == null || constraintMappings.size() == 0) 204 return Collections.emptyList(); 205 206 List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>(); 207 for (ConstraintMapping mapping:constraintMappings) 208 { 209 //Remove the matching mappings by only copying in non-matching mappings 210 if (!pathSpec.equals(mapping.getPathSpec())) 211 { 212 mappings.add(mapping); 213 } 214 } 215 return mappings; 216 } 217 218 219 220 /* ------------------------------------------------------------ */ 221 /** Generate Constraints and ContraintMappings for the given url pattern and ServletSecurityElement 222 * 223 * @param name 224 * @param pathSpec 225 * @param securityElement 226 * @return 227 */ createConstraintsWithMappingsForPath(String name, String pathSpec, ServletSecurityElement securityElement)228 public static List<ConstraintMapping> createConstraintsWithMappingsForPath (String name, String pathSpec, ServletSecurityElement securityElement) 229 { 230 List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>(); 231 232 //Create a constraint that will describe the default case (ie if not overridden by specific HttpMethodConstraints) 233 Constraint constraint = ConstraintSecurityHandler.createConstraint(name, securityElement); 234 235 //Create a mapping for the pathSpec for the default case 236 ConstraintMapping defaultMapping = new ConstraintMapping(); 237 defaultMapping.setPathSpec(pathSpec); 238 defaultMapping.setConstraint(constraint); 239 mappings.add(defaultMapping); 240 241 242 //See Spec 13.4.1.2 p127 243 List<String> methodOmissions = new ArrayList<String>(); 244 245 //make constraint mappings for this url for each of the HttpMethodConstraintElements 246 Collection<HttpMethodConstraintElement> methodConstraints = securityElement.getHttpMethodConstraints(); 247 if (methodConstraints != null) 248 { 249 for (HttpMethodConstraintElement methodConstraint:methodConstraints) 250 { 251 //Make a Constraint that captures the <auth-constraint> and <user-data-constraint> elements supplied for the HttpMethodConstraintElement 252 Constraint mconstraint = ConstraintSecurityHandler.createConstraint(name, methodConstraint); 253 ConstraintMapping mapping = new ConstraintMapping(); 254 mapping.setConstraint(mconstraint); 255 mapping.setPathSpec(pathSpec); 256 if (methodConstraint.getMethodName() != null) 257 { 258 mapping.setMethod(methodConstraint.getMethodName()); 259 //See spec 13.4.1.2 p127 - add an omission for every method name to the default constraint 260 methodOmissions.add(methodConstraint.getMethodName()); 261 } 262 mappings.add(mapping); 263 } 264 } 265 //See spec 13.4.1.2 p127 - add an omission for every method name to the default constraint 266 if (methodOmissions.size() > 0) 267 defaultMapping.setMethodOmissions(methodOmissions.toArray(new String[methodOmissions.size()])); 268 269 return mappings; 270 } 271 272 273 /* ------------------------------------------------------------ */ 274 /** Get the strict mode. 275 * @return true if the security handler is running in strict mode. 276 */ isStrict()277 public boolean isStrict() 278 { 279 return _strict; 280 } 281 282 /* ------------------------------------------------------------ */ 283 /** Set the strict mode of the security handler. 284 * <p> 285 * When in strict mode (the default), the full servlet specification 286 * will be implemented. 287 * If not in strict mode, some additional flexibility in configuration 288 * is allowed:<ul> 289 * <li>All users do not need to have a role defined in the deployment descriptor 290 * <li>The * role in a constraint applies to ANY role rather than all roles defined in 291 * the deployment descriptor. 292 * </ul> 293 * 294 * @param strict the strict to set 295 * @see #setRoles(Set) 296 * @see #setConstraintMappings(List, Set) 297 */ setStrict(boolean strict)298 public void setStrict(boolean strict) 299 { 300 _strict = strict; 301 } 302 303 /* ------------------------------------------------------------ */ 304 /** 305 * @return Returns the constraintMappings. 306 */ getConstraintMappings()307 public List<ConstraintMapping> getConstraintMappings() 308 { 309 return _constraintMappings; 310 } 311 312 /* ------------------------------------------------------------ */ getRoles()313 public Set<String> getRoles() 314 { 315 return _roles; 316 } 317 318 /* ------------------------------------------------------------ */ 319 /** 320 * Process the constraints following the combining rules in Servlet 3.0 EA 321 * spec section 13.7.1 Note that much of the logic is in the RoleInfo class. 322 * 323 * @param constraintMappings 324 * The constraintMappings to set, from which the set of known roles 325 * is determined. 326 */ setConstraintMappings(List<ConstraintMapping> constraintMappings)327 public void setConstraintMappings(List<ConstraintMapping> constraintMappings) 328 { 329 setConstraintMappings(constraintMappings,null); 330 } 331 332 /** 333 * Process the constraints following the combining rules in Servlet 3.0 EA 334 * spec section 13.7.1 Note that much of the logic is in the RoleInfo class. 335 * 336 * @param constraintMappings 337 * The constraintMappings to set as array, from which the set of known roles 338 * is determined. Needed to retain API compatibility for 7.x 339 */ setConstraintMappings( ConstraintMapping[] constraintMappings )340 public void setConstraintMappings( ConstraintMapping[] constraintMappings ) 341 { 342 setConstraintMappings( Arrays.asList(constraintMappings), null); 343 } 344 345 /* ------------------------------------------------------------ */ 346 /** 347 * Process the constraints following the combining rules in Servlet 3.0 EA 348 * spec section 13.7.1 Note that much of the logic is in the RoleInfo class. 349 * 350 * @param constraintMappings 351 * The constraintMappings to set. 352 * @param roles The known roles (or null to determine them from the mappings) 353 */ setConstraintMappings(List<ConstraintMapping> constraintMappings, Set<String> roles)354 public void setConstraintMappings(List<ConstraintMapping> constraintMappings, Set<String> roles) 355 { 356 _constraintMappings.clear(); 357 _constraintMappings.addAll(constraintMappings); 358 359 if (roles==null) 360 { 361 roles = new HashSet<String>(); 362 for (ConstraintMapping cm : constraintMappings) 363 { 364 String[] cmr = cm.getConstraint().getRoles(); 365 if (cmr!=null) 366 { 367 for (String r : cmr) 368 if (!"*".equals(r)) 369 roles.add(r); 370 } 371 } 372 } 373 setRoles(roles); 374 375 if (isStarted()) 376 { 377 for (ConstraintMapping mapping : _constraintMappings) 378 { 379 processConstraintMapping(mapping); 380 } 381 } 382 } 383 384 /* ------------------------------------------------------------ */ 385 /** 386 * Set the known roles. 387 * This may be overridden by a subsequent call to {@link #setConstraintMappings(ConstraintMapping[])} or 388 * {@link #setConstraintMappings(List, Set)}. 389 * @see #setStrict(boolean) 390 * @param roles The known roles (or null to determine them from the mappings) 391 */ setRoles(Set<String> roles)392 public void setRoles(Set<String> roles) 393 { 394 _roles.clear(); 395 _roles.addAll(roles); 396 } 397 398 399 400 /* ------------------------------------------------------------ */ 401 /** 402 * @see org.eclipse.jetty.security.ConstraintAware#addConstraintMapping(org.eclipse.jetty.security.ConstraintMapping) 403 */ addConstraintMapping(ConstraintMapping mapping)404 public void addConstraintMapping(ConstraintMapping mapping) 405 { 406 _constraintMappings.add(mapping); 407 if (mapping.getConstraint()!=null && mapping.getConstraint().getRoles()!=null) 408 for (String role : mapping.getConstraint().getRoles()) 409 addRole(role); 410 411 if (isStarted()) 412 { 413 processConstraintMapping(mapping); 414 } 415 } 416 417 /* ------------------------------------------------------------ */ 418 /** 419 * @see org.eclipse.jetty.security.ConstraintAware#addRole(java.lang.String) 420 */ addRole(String role)421 public void addRole(String role) 422 { 423 boolean modified = _roles.add(role); 424 if (isStarted() && modified && _strict) 425 { 426 // Add the new role to currently defined any role role infos 427 for (Map<String,RoleInfo> map : (Collection<Map<String,RoleInfo>>)_constraintMap.values()) 428 { 429 for (RoleInfo info : map.values()) 430 { 431 if (info.isAnyRole()) 432 info.addRole(role); 433 } 434 } 435 } 436 } 437 438 /* ------------------------------------------------------------ */ 439 /** 440 * @see org.eclipse.jetty.security.SecurityHandler#doStart() 441 */ 442 @Override doStart()443 protected void doStart() throws Exception 444 { 445 _constraintMap.clear(); 446 if (_constraintMappings!=null) 447 { 448 for (ConstraintMapping mapping : _constraintMappings) 449 { 450 processConstraintMapping(mapping); 451 } 452 } 453 super.doStart(); 454 } 455 456 457 /* ------------------------------------------------------------ */ 458 @Override doStop()459 protected void doStop() throws Exception 460 { 461 _constraintMap.clear(); 462 _constraintMappings.clear(); 463 _roles.clear(); 464 super.doStop(); 465 } 466 467 468 /* ------------------------------------------------------------ */ 469 /** 470 * Create and combine the constraint with the existing processed 471 * constraints. 472 * 473 * @param mapping 474 */ processConstraintMapping(ConstraintMapping mapping)475 protected void processConstraintMapping(ConstraintMapping mapping) 476 { 477 Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.get(mapping.getPathSpec()); 478 if (mappings == null) 479 { 480 mappings = new StringMap(); 481 _constraintMap.put(mapping.getPathSpec(),mappings); 482 } 483 RoleInfo allMethodsRoleInfo = mappings.get(null); 484 if (allMethodsRoleInfo != null && allMethodsRoleInfo.isForbidden()) 485 return; 486 487 if (mapping.getMethodOmissions() != null && mapping.getMethodOmissions().length > 0) 488 { 489 490 processConstraintMappingWithMethodOmissions(mapping, mappings); 491 return; 492 } 493 494 String httpMethod = mapping.getMethod(); 495 RoleInfo roleInfo = mappings.get(httpMethod); 496 if (roleInfo == null) 497 { 498 roleInfo = new RoleInfo(); 499 mappings.put(httpMethod,roleInfo); 500 if (allMethodsRoleInfo != null) 501 { 502 roleInfo.combine(allMethodsRoleInfo); 503 } 504 } 505 if (roleInfo.isForbidden()) 506 return; 507 508 //add in info from the constraint 509 configureRoleInfo(roleInfo, mapping); 510 511 if (roleInfo.isForbidden()) 512 { 513 if (httpMethod == null) 514 { 515 mappings.clear(); 516 mappings.put(null,roleInfo); 517 } 518 } 519 else 520 { 521 //combine with any entry that covers all methods 522 if (httpMethod == null) 523 { 524 for (Map.Entry<String, RoleInfo> entry : mappings.entrySet()) 525 { 526 if (entry.getKey() != null) 527 { 528 RoleInfo specific = entry.getValue(); 529 specific.combine(roleInfo); 530 } 531 } 532 } 533 } 534 } 535 536 /* ------------------------------------------------------------ */ 537 /** Constraints that name method omissions are dealt with differently. 538 * We create an entry in the mappings with key "method.omission". This entry 539 * is only ever combined with other omissions for the same method to produce a 540 * consolidated RoleInfo. Then, when we wish to find the relevant constraints for 541 * a given Request (in prepareConstraintInfo()), we consult 3 types of entries in 542 * the mappings: an entry that names the method of the Request specifically, an 543 * entry that names constraints that apply to all methods, entries of the form 544 * method.omission, where the method of the Request is not named in the omission. 545 * @param mapping 546 * @param mappings 547 */ processConstraintMappingWithMethodOmissions(ConstraintMapping mapping, Map<String, RoleInfo> mappings)548 protected void processConstraintMappingWithMethodOmissions (ConstraintMapping mapping, Map<String, RoleInfo> mappings) 549 { 550 String[] omissions = mapping.getMethodOmissions(); 551 552 for (String omission:omissions) 553 { 554 //for each method omission, see if there is already a RoleInfo for it in mappings 555 RoleInfo ri = mappings.get(omission+OMISSION_SUFFIX); 556 if (ri == null) 557 { 558 //if not, make one 559 ri = new RoleInfo(); 560 mappings.put(omission+OMISSION_SUFFIX, ri); 561 } 562 563 //initialize RoleInfo or combine from ConstraintMapping 564 configureRoleInfo(ri, mapping); 565 } 566 } 567 568 569 /* ------------------------------------------------------------ */ 570 /** 571 * Initialize or update the RoleInfo from the constraint 572 * @param ri 573 * @param mapping 574 */ configureRoleInfo(RoleInfo ri, ConstraintMapping mapping)575 protected void configureRoleInfo (RoleInfo ri, ConstraintMapping mapping) 576 { 577 Constraint constraint = mapping.getConstraint(); 578 boolean forbidden = constraint.isForbidden(); 579 ri.setForbidden(forbidden); 580 581 //set up the data constraint (NOTE: must be done after setForbidden, as it nulls out the data constraint 582 //which we need in order to do combining of omissions in prepareConstraintInfo 583 UserDataConstraint userDataConstraint = UserDataConstraint.get(mapping.getConstraint().getDataConstraint()); 584 ri.setUserDataConstraint(userDataConstraint); 585 586 587 //if forbidden, no point setting up roles 588 if (!ri.isForbidden()) 589 { 590 //add in the roles 591 boolean checked = mapping.getConstraint().getAuthenticate(); 592 ri.setChecked(checked); 593 if (ri.isChecked()) 594 { 595 if (mapping.getConstraint().isAnyRole()) 596 { 597 if (_strict) 598 { 599 // * means "all defined roles" 600 for (String role : _roles) 601 ri.addRole(role); 602 } 603 else 604 // * means any role 605 ri.setAnyRole(true); 606 } 607 else 608 { 609 String[] newRoles = mapping.getConstraint().getRoles(); 610 for (String role : newRoles) 611 { 612 if (_strict &&!_roles.contains(role)) 613 throw new IllegalArgumentException("Attempt to use undeclared role: " + role + ", known roles: " + _roles); 614 ri.addRole(role); 615 } 616 } 617 } 618 } 619 } 620 621 622 /* ------------------------------------------------------------ */ 623 /** 624 * Find constraints that apply to the given path. 625 * In order to do this, we consult 3 different types of information stored in the mappings for each path - each mapping 626 * represents a merged set of user data constraints, roles etc -: 627 * <ol> 628 * <li>A mapping of an exact method name </li> 629 * <li>A mapping will null key that matches every method name</li> 630 * <li>Mappings with keys of the form "method.omission" that indicates it will match every method name EXCEPT that given</li> 631 * </ol> 632 * 633 * @see org.eclipse.jetty.security.SecurityHandler#prepareConstraintInfo(java.lang.String, org.eclipse.jetty.server.Request) 634 */ prepareConstraintInfo(String pathInContext, Request request)635 protected Object prepareConstraintInfo(String pathInContext, Request request) 636 { 637 Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.match(pathInContext); 638 639 if (mappings != null) 640 { 641 String httpMethod = request.getMethod(); 642 RoleInfo roleInfo = mappings.get(httpMethod); 643 if (roleInfo == null) 644 { 645 //No specific http-method names matched 646 List<RoleInfo> applicableConstraints = new ArrayList<RoleInfo>(); 647 648 //Get info for constraint that matches all methods if it exists 649 RoleInfo all = mappings.get(null); 650 if (all != null) 651 applicableConstraints.add(all); 652 653 654 //Get info for constraints that name method omissions where target method name is not omitted 655 //(ie matches because target method is not omitted, hence considered covered by the constraint) 656 for (Entry<String, RoleInfo> entry: mappings.entrySet()) 657 { 658 if (entry.getKey() != null && entry.getKey().contains(OMISSION_SUFFIX) && !(httpMethod+OMISSION_SUFFIX).equals(entry.getKey())) 659 applicableConstraints.add(entry.getValue()); 660 } 661 662 if (applicableConstraints.size() == 1) 663 roleInfo = applicableConstraints.get(0); 664 else 665 { 666 roleInfo = new RoleInfo(); 667 roleInfo.setUserDataConstraint(UserDataConstraint.None); 668 669 for (RoleInfo r:applicableConstraints) 670 roleInfo.combine(r); 671 } 672 673 } 674 return roleInfo; 675 } 676 return null; 677 } 678 679 680 /* ------------------------------------------------------------ */ 681 /** 682 * @see org.eclipse.jetty.security.SecurityHandler#checkUserDataPermissions(java.lang.String, org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response, java.lang.Object) 683 */ checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo)684 protected boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException 685 { 686 if (constraintInfo == null) 687 return true; 688 689 RoleInfo roleInfo = (RoleInfo)constraintInfo; 690 if (roleInfo.isForbidden()) 691 return false; 692 693 694 UserDataConstraint dataConstraint = roleInfo.getUserDataConstraint(); 695 if (dataConstraint == null || dataConstraint == UserDataConstraint.None) 696 { 697 return true; 698 } 699 AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection(); 700 Connector connector = connection.getConnector(); 701 702 if (dataConstraint == UserDataConstraint.Integral) 703 { 704 if (connector.isIntegral(request)) 705 return true; 706 if (connector.getIntegralPort() > 0) 707 { 708 String scheme=connector.getIntegralScheme(); 709 int port=connector.getIntegralPort(); 710 String url = (HttpSchemes.HTTPS.equalsIgnoreCase(scheme) && port==443) 711 ? "https://"+request.getServerName()+request.getRequestURI() 712 : scheme + "://" + request.getServerName() + ":" + port + request.getRequestURI(); 713 if (request.getQueryString() != null) 714 url += "?" + request.getQueryString(); 715 response.setContentLength(0); 716 response.sendRedirect(url); 717 } 718 else 719 response.sendError(Response.SC_FORBIDDEN,"!Integral"); 720 721 request.setHandled(true); 722 return false; 723 } 724 else if (dataConstraint == UserDataConstraint.Confidential) 725 { 726 if (connector.isConfidential(request)) 727 return true; 728 729 if (connector.getConfidentialPort() > 0) 730 { 731 String scheme=connector.getConfidentialScheme(); 732 int port=connector.getConfidentialPort(); 733 String url = (HttpSchemes.HTTPS.equalsIgnoreCase(scheme) && port==443) 734 ? "https://"+request.getServerName()+request.getRequestURI() 735 : scheme + "://" + request.getServerName() + ":" + port + request.getRequestURI(); 736 if (request.getQueryString() != null) 737 url += "?" + request.getQueryString(); 738 response.setContentLength(0); 739 response.sendRedirect(url); 740 } 741 else 742 response.sendError(Response.SC_FORBIDDEN,"!Confidential"); 743 744 request.setHandled(true); 745 return false; 746 } 747 else 748 { 749 throw new IllegalArgumentException("Invalid dataConstraint value: " + dataConstraint); 750 } 751 752 } 753 754 /* ------------------------------------------------------------ */ 755 /** 756 * @see org.eclipse.jetty.security.SecurityHandler#isAuthMandatory(org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response, java.lang.Object) 757 */ isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo)758 protected boolean isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo) 759 { 760 if (constraintInfo == null) 761 { 762 return false; 763 } 764 return ((RoleInfo)constraintInfo).isChecked(); 765 } 766 767 768 /* ------------------------------------------------------------ */ 769 /** 770 * @see org.eclipse.jetty.security.SecurityHandler#checkWebResourcePermissions(java.lang.String, org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response, java.lang.Object, org.eclipse.jetty.server.UserIdentity) 771 */ 772 @Override checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo, UserIdentity userIdentity)773 protected boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo, UserIdentity userIdentity) 774 throws IOException 775 { 776 if (constraintInfo == null) 777 { 778 return true; 779 } 780 RoleInfo roleInfo = (RoleInfo)constraintInfo; 781 782 if (!roleInfo.isChecked()) 783 { 784 return true; 785 } 786 787 if (roleInfo.isAnyRole() && request.getAuthType()!=null) 788 return true; 789 790 for (String role : roleInfo.getRoles()) 791 { 792 if (userIdentity.isUserInRole(role, null)) 793 return true; 794 } 795 return false; 796 } 797 798 /* ------------------------------------------------------------ */ 799 @Override dump(Appendable out,String indent)800 public void dump(Appendable out,String indent) throws IOException 801 { 802 dumpThis(out); 803 dump(out,indent, 804 Collections.singleton(getLoginService()), 805 Collections.singleton(getIdentityService()), 806 Collections.singleton(getAuthenticator()), 807 Collections.singleton(_roles), 808 _constraintMap.entrySet(), 809 getBeans(), 810 TypeUtil.asList(getHandlers())); 811 } 812 813 } 814