指定安全约束
安全约束是一种定义 web 内容保护的声明式方式。安全约束关联授权和或在 web 资源上对 HTTP 操作的用户数据约束。安全约束,在部署描述符中由 security-constraint 表示,其包含以下元素:
- web资源集合 (部署描述符中的 web-resource-collection)
- 授权约束 (部署描述符中的 auth-constraint)
- 用户数据约束 (部署描述符中的 user-data-constraint) HTTP操作和网络资源的安全约束应用(即受限的请求)根据一个或多个web资源集合识别。Web资源集合包含以下元素:
- URL 模式 (部署描述符中的url-pattern)
- HTTP methods (部署描述符中的 http-method 或 http-method-omission 元素)
授权约束规定认证和命名执行受约束请求的被许可的授权角色的要求。用户必须至少是许可执行受约束请求的命名角色中的一个成员。特殊角色名“”是定义在部署描述符中的所有角色名的一种简写。特殊的角色名“*”是一种用于任何授权的用户不受约束的角色的速记法。它表示任何授权的用户,不受约束的角色,被授权允许执行约束的请求。没有指定角色的授权约束表示在任何情况下不允许访问受约束请求。授权约束包含以下元素:
- role name (部署描述符中的role-name)
用户数据约束规定了在受保护的传输层连接之上接收受约束的请求的要求。需要保护的强度由传输保障的值定义。INTEGRAL类型的传输保障用于规定内容完整性要求,且传输保障CONFIDENTIAL用于规定保密性要求的。传输保障“NONE”表示当容器通过任何包括不受保护的连接接受到请求时,必须接受此受约束的请求。容器可能在响应中强加一个受信的传输保障(confidential transport guarantee)为INTEGRAL值。 用户数据约束包括如下元素:
- transport guarantee (部署描述符中的transport-guarantee)
如果没有授权约束应用到请求,容器必须接受请求,而不要求用户身份认证。如果没有用户数据约束应用到请求,当容器通过任何包括不受保护的连接接收到请求时,必须接受此请求。
组合约束
为了组合约束,HTTP 方法可以说是存在于 web-resource-collection中,仅当没有在集合中指定 HTTP 方法,或者集合在包含的 http-method 元素中具体指定了 HTTP 方法,或者集合包含一个或多个 http-method-omission 元素,但那些没有指定的 HTTP 方法。 当url-pattern 和 HTTP 方法以组合方式(即,在 web-resource-collection 中)出现在多个安全约束中,该约束(在模式和方法上的)是通过合并单个约束定义的。以相同的模式和方法出现的组合约束规则如下所示:
授权约束组合,其明确指定角色或通过“” 隐式指定角色,可产生单个约束的合并的角色名称作为许可的角色。一个命名角色“*”的授权约束将与授权约束命名的或隐式的角色组合以允许任何授权的用户不受约束的角色。不包含授权约束的安全约束将与明确指定角色的或隐式指定角色的允许未授权访问的安全约束合并。授权约束的一个特殊情况是其没有指定角色,将与任何其他约束合并并覆盖它们的作用,这导致访问被阻止。
应用到常见的 url-pattern 和 http-method 的 user-data-constraint 组合,可产生合并的单个约束接受的连接类型作为接受的连接类型。不包含 user-data-constraint 的安全约束,将与其他 user-data-constraint 合并,使不安全的连接类型是可接受的连接类型。
示例
下面的示例演示了组合约束及它们翻译到的可应用的约束表格。假设部署描述符包含如下安全约束。
<security-constraint>
<web-resource-collection>
<web-resource-name>precluded methods</web-resource-name>
<url-pattern>/*</url-pattern>
<url-pattern>/acme/wholesale/*</url-pattern>
<url-pattern>/acme/retail/*</url-pattern>
<http-method-omission>GET</http-method-omission>
<http-method-omission>POST</http-method-omission>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>wholesale</web-resource-name>
<url-pattern>/acme/wholesale/*</url-pattern>
<http-method>GET</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>SALESCLERK</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>wholesale 2</web-resource-name>
<url-pattern>/acme/wholesale/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>CONTRACTOR</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>retail</web-resource-name>
<url-pattern>/acme/retail/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>CONTRACTOR</role-name>
<role-name>HOMEOWNER</role-name>
</auth-constraint>
</security-constraint>
转化这个假定的部署描述符将产生定义在表13-4中的约束。
TABLE 13-4 Security Constraint Table
url-pattern | http 方法 | 许可的角色 | 支持的连接类型 |
---|---|---|---|
/* | 所有除 GET,POST 的方法 | 阻止访问 | 不限制 |
/acme/wholesale/* | 所有除 GET,POST 的方法 | 阻止访问 | 不限制 |
/acme/wholesale/* | GET | CONTRACTOR SALESCLERK | 不限制 |
/acme/wholesale/* | POST | CONTRACTOR | CONFIDENTIAL |
/acme/retail/* | 所有除 GET,POST 的方法 | 阻止访问 | 不限制 |
/acme/retail/* | GET | CONTRACTOR HOMEOWNER | 不限制 |
/acme/retail/* | POST | CONTRACTOR HOMEOWNER | 不限制 |
处理请求
当 servlet 容器接收到一个请求,它将使用119页“使用URL路径”描述的规则来选择在请求URI最佳匹配的url-pattern上定义的约束(如果有)。如果没有约束被选择,容器将接受该请求。否则,容器将确定在选择的模式上是否此请求的HTTP方法是受约束的。如果不是,请求将被接受。否则,请求必须满足在urlpattern应用到HTTP方法的约束。请求被接受和分派到相关的servlet,必须满足以下两个规则。
- 接收到的请求的连接特性必须满足至少一种由约束定义的支持的连接类型。如果该规则不满足,容器将拒绝该请求并重定向到HTTPS端口。(作为一种优化,容器将以拒绝该请求为forbidden 并返回403 (SC_FORBIDDEN)状态码,如果知道该访问将最终将被阻止 (通过没有指定角色的授权约束))
- 请求的认证特性必须满足任何由约束定义的认证和角色要求。如果该规则不能满足是因为访问已经被阻止(通过没有指定角色的授权约束),则请求将被拒绝为forbidden 并返回403 (SC_FORBIDDEN)状态码。如果访问是受限于许可的角色且请求还没有被认证,则请求将被拒绝为unauthorized 且401(SC_UNAUTHORIZED)状态码将被返回以导致身份认证。如果访问是受限于许可的角色且请求的认证身份不是这些角色中的成员,则请求将被拒绝为forbidden 且403状态码(SC_FORBIDDEN)将被返回到用户。
未覆盖的 HTTP 协议方法
security-constraint schema提供了枚举(包括省略)定义在security-constraint 中的保护要求应用到哪一个HTTP方法的能力。当HTTP 方法枚举在 security-constraint,约束定义的保护仅应用到枚举建立的方法。我们把不是枚举建立的方法称为“未覆盖的”HTTP方法。未覆盖的 HTTP 方法不保护所有 security-constraint 的 url-pattern 最匹配的请求的 URL。
当 HTTP 方法没有枚举在一个 security-constraint 中时,约束定义的保护应用到完整的HTTP(扩展)方法集。在那种情况,在那些 security-constraint的url-pattern 最佳匹配的所有请求的URL,没有未覆盖的HTTP方法。
例子用三种方式描述了在哪些 HTTP 协议方法可能未覆盖。方法是否是未覆盖的是由在所有约束应用到一个 url-pattern 已经按照113.8.1节,“组合约束”组合决定的。
security-constraint 在 http-method 元素中命名一个或多个 HTTP 方法。除了那些明明在约束中的,所有 HTTP 方法是未覆盖的。
<web-resource-collection>
<web-resource-name>wholesale</web-resource-name>
<url-pattern>/acme/wholesale/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>SALESCLERK</role-name>
</auth-constraint>
除了GET,所以HTTP方法是未覆盖的。
security-constriant在http-method-omission元素中命名一个或多个HTTP方法。所有命名在约束中的HTTP方法是未覆盖的
<web-resource-collection>
<web-resource-name>wholesale</web-resource-name>
<url-pattern>/acme/wholesale/*</url-pattern>
<http-method-omission>GET</http-method-omission>
</web-resource-collection>
<auth-constraint/>
GET是未覆盖的。所有其他方法是被排除的auth-constraint覆盖的。
包括一个 @HttpConstraint 的 @ServletSecurity 注解返回所有默认值,且也包括至少一个返回除了所有默认值之外的@HttpMethodConstraint。除了那些命名在 @HttpMethodConstraint 中的所有 HTTP 方法是被注解未覆盖的。这种情况是与情况1是类似的,且等价于使用 ServletRegistration 接口的 setServletSecurity 方法也将产生一个类似的结果。
@ServletSecurity((httpMethodConstraints = { @HttpMethodConstraint(value = “GET”, rolesAllowed = “R1”), @HttpMethodConstraint(value = “POST”, rolesAllowed = “R1”, transportGuarantee = TransportGuarantee.CONFIDENTIAL) }) public class Example5 extends HttpServlet { }
除了GET和POST之外的所有HTTP方法是未覆盖的。
安全约束配置规则
目的:确保在所有约束的 URL 模式上的所有HTTP方法有预期的安全保护(即,覆盖的)。
- 没有在约束中命名 HTTP 方法;在这种情况下,未 URL 模式定义的安全保护将应用到所有 HTTP 方法。
- 如果你不能遵循规则#1,添加
<deny-uncovered-http-methods>
和声明(使用<http-method>
元素,或等价的注解)所有在约束URL模式允许的HTTP方法(有安全保护)。 - 如果你不能遵循规则#2,声明约束来覆盖每一个约束的URL模式的所有HTTP方法。使用
<http-method-omission>
元素或HttpMethodConstraint 注解来表示除了被<http-method>
或HttpMethodConstraint 命名的那些之外的所有 HTTP 方法集。当使用注解时,使用 HttpConstraint 定义应用到所有其他 HTTP 方法和配置EmptyRoleSemantic=DENY 来导致所有其他 HTTP 方法被拒绝的安全语义。
处理未覆盖的HTTP方法
在应用部署期间,容器必须通知部署人员任何存在于从为应用定义的约束组合产生的应用安全约束配置中的未覆盖的 HTTP 方法。提供的信息必须标识未覆盖的 HTTP 协议方法,和在 HTTP 方法未覆盖那些相关的URL模式。通知部署人员的要求可以通过记录必需的信息来满足。
当 deny-uncovered-http-methods 标记在应用的 web.xml 中设置了,容器必须拒绝任何 HTTP 协议方法,当它用于一个其 HTTP 方法在应用到请求 URL 最佳匹配的 url-pattern 的组合安全约束请求URL是未覆盖的。拒绝的请求将被拒绝为 forbidden 并返回一个 403(SC_FORBIDDEN)状态码。
导致未覆盖的 HTTP 方法为拒绝,部署系统将建立额外的排除 auth-constraint,去覆盖这些在未覆盖的HTTP方法约束的 url-pattern 的HTTP 方法。
当应用的安全配置不包含未覆盖的方法,deny-uncovered-http-methods标记在应用的有效的安全配置上必须没有效果。
应用deny-uncovered-http-methods 到一个应用,其安全配置包含未覆盖的方法,可能,在一些情况下,拒绝访问资源为了应用的功能必须是可访问的。这这种情况下,应用的安全配置应该完成所有未覆盖的方法被相关约束配置覆盖。
应用开发人员应该定义安全约束配置,没有任何未覆盖的 HTTP 方法,且他们应该设置 deny-uncovered-http-methods 标记确保他们的应用不会依赖于通过未覆盖的方法来得到可访问性。
Servlet 容器可以提供一个配置选项来选择未覆盖方法的默认行为是ALLOW 还是 DENY。这个选项可以配置在每容器粒度或更大。注意,设置这个默认为 DENY 可能导致一些应用失败。