Servlet 3.0 之 安全

Web应用被应用开发者创建,这些开发者给予、卖应用,或者为了安装到一个运行时环境,把应用转移应用到一个部署者。应用开发者会把安全要求传达给部署者和部署系统。这个信息可能会通过应用的部署描述符或者在应用代码里使用注解明确地表达。
本章为了表达应用的安全需求,描述了Servlet容器安全机制、接口、部署描述符和注解机制。

一、介绍

一个web应用包含能被很多用户访问的资源。这些资源通常在没有保护和开放网络上传输,如Internet。在这样的环境中,大量web应用将会有安全需求。
虽然质量保障和实现细节可能不同,servlet容器有机制和基础设施来满足共享下列特征的需求:

  • Authentication: 交流实体要向对方证明它们是在授权的特殊身份上访问。
  • Access control for resources: 与资源的交互被限制在用户的集合中,或者为了强制一致性、可靠性或者可用性限制编程。
  • Data Integrity: 这被用来证明在数据传输过程中,信息没有被第三方修改。
  • ** Confidentiality or Data Privacy:**这被用来保证信息仅对那些被授权的用户访问。

二、声明式安全

声明式安全指表达一个应用安全模型或者需求的方式,包括角色,访问控制以及在一个应用外部形势的授权要求。部署描述符在web应用中是主要的工具。
开发者把应用的逻辑安全需求映射到一个与具体运行时环境相关的安全策略代表上。在运行时中,servlet容器使用安全策略代表来强制认证和授权。
安全模型应用在web应用中的静态内容部分和被客户端请求的应用中的servlets和filters上。当一个servlet使用RequestDispatcher调用一个静态资源或者使用一个forward或者includeservlet时,安全模型并不会应用生效。

三、编程式安全

当声明式安全不足以表达应用的安全模型时,编程式安全被安全意识应用使用。编程式安全由HttpServletRequest接口的下列方法组成:
* authenticate
* login
* logout
* getRemoteUser
* isUserInRole
* getUserPrincipal

login方法允许一个应用执行用户名和密码集合(还有一种基于表单的登录)。authenticate方法允许一个应用从一个没有限制的请求上下文中激起请求调用者的认证。
logout方法允许一个应用重置一个请求的调用身份。
getRemote方法返回与请求关联的调用者名字。
isUserPrincipal方法决定与请求关联的调用者是否是一个指定的安全角色。
getUserPrincipal方法决定了远端调用者的主要名字,并且返回一个与远端调用者对应的java.security.Principal对象。在getUserPrincipal返回的Principal上调用getName方法会返回一个远端调用者的名字。这些APIs允许servlets基于获取的信息来决定业务逻辑。
如果没有用户已经被授权,getRemoteUser方法返回null,isUserInRole方法总会返回false,并且getUserPrincipal方法返回null。
isUserInRole方法期望一个表示用户角色名字的字符串参数。security-role-ref元素应该在部署描述符中被声明,并且有一个包含传递给方法的角色名字的role-name子元素。一个security-role-ref元素应该包含一个角色链接子元素,它的值是用户被映射到的安全角色的名字。当决定调用的返回值时,容器使用security-role-refsecurity-role的映射。
比如,把安全角色引用FOO映射到名字为manager的安全角色。语法如下
<security-role-ref>
<role-name>FOO</role-name>
<role-link>manager</role-link>
</security-role-ref>
这个例子中,如果被属于manager安全角色的用户调用的servlet调用API方法isUserInRole,结果将会是true。
如果没有匹配一个security-rolesecurity-role-ref元素已经被声明,容器必须默认对web应用的security-role元素列表检查role-name元素参数。isUserInRole方法参考这个列表来决定调用者是否被映射到一个安全角色。开发者必须意识到这个默认机制的使用在改变应用中角色名字的时候限制灵活性,改变角色名字不必重新编译servlet来调用。

四、编程式访问控制注解

本节定义了注解和apis,用来配置Servlet容器强制的安全限制。

  1. @ServletSecurity Annotation
    @ServletSecurity注解为定义访问控制限制提供了一种替代机制,这等价于通过可移植部署描述符中的security-constraint元素声明或者通过ServletRegistration接口的setServletSecurity方法编程式声明。Servlet容器必须支持在实现了javax.servlet.Servlet 接口的类上使用@ServletSecurity注解。
    package javax.servlet.annotation;
    @Inherited
    @Documented
    @Target(value=TYPE)
    @Retention(value=RUNTIME)
    public @interface ServletSecurity {
    HttpConstraint value();
    HttpMethodConstraint[] httpMethodConstraints();
    }
    Table 1-1 ServletSecurity Interface
Element 描述 默认
value HttpConstraint定义了应用于所有没出现在httpMethodConstraints返回数组中的HTTP方法的保护。 @HttpConstraint
httpMethodConstraints HTTP方法具体限制的数组 {}

@HttpConstraint
@HttpConstraint注解在@ServletSecurity注解中被使用来代表应用于所有HTTP协议方法的安全限制,一个对应的@HttpMethodConstraint没有为上述方法出现在@ServletSecurity注解中。

package javax.servlet.annotation
@Documented
@Retention(value=RUNTIME)
public @interface HttpConstraint {
  ServletSecurity.EmptyRoleSemantic value();
  java.lang.String[] rolesAllowed();
  ServletSecurity.TransportGuarantee transportGuarantee();
}

Table 1-2 HttpConstraint接口

Element 描述 默认
value 默认的授权语义,仅当rolesAllowed返回空数组时应用。 PERMIT
rolesAllowed 包含授权角色名字的一个数组 {}
transportGuarantee 数据保护要求,必须被请求到达的连接上被满足 NONE

@HttpMethodConstraint
@HttpMethodConstraint注解在具体HTTP协议消息上代表安全限制的@ServletSecurity注解中被使用。

package javax.servlet.annotation
@Documented
@Retention(value=RUNTIME)
public @interface HttpMethodContraint {
  ServletSecurity.EmptyRoleSemantic value();
  java.lang.String[] rolesAllowed();
  ServletSecurity.TransportGuarantee transportGuarantee();
}
Element 描述 默认
value HTTP协议方法名字
emptyRoleSemantic 默认授权机制,仅当rolesAllowed返回空字符串时应用 PERMIT
rolesAllowed 包含已授权角色名字的一个数组 {}
transportGuarantee 数据保护需求,必须被请求到达的连接满足 NONE

@ServletSecurity注解可以在一个Servlet实现类上被指明,并且它的值被为根据元注解@Inherited规则定义的子类继承。@ServletSecurity注解的一个实例可以出现在一个Servlet实现类上面,并且@ServletSecurity注解一定不能在一个Java方法上被指定。
当一个或者多个@HttpMethodConstraint注解在一个@ServletSecurity注解里面被定义,每个@HttpMethodConstraint定义了security-constraint,它应用在所有HTTP协议方法上,而不是那些一个对应HttpMethodConstraint@ServletSecurity注解中被定义的方法上。
定义在可移植部署描述符中的security-constraint元素对所有出现在限制里的url-patterns的有权限。
当在可移植部署描述符中的一个security-constraint包含一个映射到一个用@ServletSecurity注解的类的一个精确匹配的url-pattern,注解一定不能影响Servlet容器在pattern上的强行限制。
当一个类上没有使用@ServletSecurity,应用于从那个类映射而来的一个servlet的访问策略(如果有的话)在对应的部署描述符中被适用的security-constraint元素建立,或者除了任何这些元素,通过ServletRegistration接口的setServletSecurity方法编程式地为目标servlet建立。

  • 例子
    下列例子说明了ServletSecurity注解的使用。
    CODE EXAMPLE 4-1 对于所有的HTTP方法,没有限制
    @ServletSecurity
    public class Example1 extends HttpServlet {
    }
    CODE EXAMPLE 4-2 对所有HTTP方法,没有授权约束,加密传输要求
    @ServletSecurity(@HttpConstraint(transportGuarantee=TransportGuarantee.CONFIDENTIAL))
    public class Example2 extends HttpServlet {
    }
    CODE EXAMPLE 4-3 对所有HTTP方法,所有访问都被拒绝
    @ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY))
    public class Example3 extends HttpServlet {
    }
    CODE EXAMPLE 4-4 对所有HTTP方法,要求角色R1成员的权限约束
    @ServletSecurity(@HttpConstraint(rolesAllowed="R1"))
    public class Example4 extends HttpServlet {
    }
    CODE EXAMPLE 4-5 对所有除了GET和POST的HTTP方法,没有约束;对GET和POST方法,要求Role R1成员的权限约束,加密传输要求。
    @ServletSecurity((httpMethodConstraints = { @HttpMethodConstraint(value="GET", rolesAllowed="R1"), @HttpMethodConstraint(value="POST", rolesAllowed="R1", transportGuarantee=TransportGuarantee.CONFIDENTIAL)})
    public class Example5 extends HttpServlet {
    }
    CODE EXAMPLE 4-6 对除了GET的所有HTTP方法要求Role R1中成员的权限约束,对于GET,没有约束。
    @ServletSecurity(value = @HttpMethodConstraints(rolesAllowed = "R1"), httpMethodConstraints = @HttpMethodConstraint("Get"))
    public class Example6 extends HttpServlet {
    }
    CODE EXAMPLE 4-7 对于除了TRACE的所有HTTP方法,要求Role R1中成员的权限约束;对于TRACE, 所有访问都拒绝。
    @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"), httpMethodConstraints = @HttpMethodConstraint(value="TRACE", emptyRoleSemantic = EmptyRoleSemantic.DENY))
    public class Example7 extends HttpServlet {
    }

  • 把@ServletSecurity映射到安全约束
    本节描述了@ServletSecurity注解到它等价表示,如security-constraint 元素的映射。它使用已存在的容器security-constraint执行机制来促进执行。@ServletSecurity注解的强制性等价于security-constraint元素的强制性。
    @ServletSecurity注解被用来定义一个方法依赖的@HttpConstraint,并且其后会跟着0个或者多个@HttpMethodConstraint说明。方法依赖的约束应用于所有没有定义HTTP具体方法约束的HTTP方法。
    当没有包含@HttpMethodConstraint元素,对应包含一个不含http-method元素的web-resource-collection的单个security-constraint元素的@ServletSecurity注解适用于所有HTTP方法。
    下列例子描绘了一个不包含@HttpMethodConstraint注解作为单个security-constraint元素的@ServletSecurity注解表示。被对应servlet定义的url-pattern元素将会被包含在web-resource-collection中,并且任何被包含的auth-constraintuser-data-constraint元素的出现和值将会通过@HttpConstraint值的映射被决定。
    CODE EXAMPLE 4-8 映射不包含@HttpMethodConstraint的@ServletSecurity
    @ServletSecurity(@HttpConstraint(rolesAllowed = "R1"))
    <security-constraint>
    <web-resource-collection>
    <url-pattern>...</url-pattern>
    </web-resource-collection>
    <auth-constraint>
    <role-name>Role1</role-name>
    <auth-constraint>
    </security-constraint>
    当一个或者多个@HttpMethodConstraint元素被指定,方法依赖约束对应单个security-constraint,它包含一个为每个命名在具体方法下的HTTP方法限制于http-method-omission元素上的web-resource-collection。每个@HttpMethodConstraint对应于另外一个包含web-resource-collectionsecurity-constraint,这个web-resource-collection包含一个命名对应HTTP方法的http-method元素。下列例子描绘了由单个约束的@HttpMethodConstraint的一个@ServletSecurity注解到两个security-constraint元素的映射。被对应servlet定义的url-pattern元素将会被包含在web-resource-collection中,并且任何包含auth-constraintuser-data-constraint元素的出现和元素将会通过相关@HttpConstraint@HttpMethodConstraint值的映射来决定。
    CODE EXAMPLE 4-9 映射包含@HttpMethodConstraint的@ServletSecurity
    @ServletSecurity(value=@HttpConstraint(rolesAllowed = "Role1"), httpMethodConstraints = @HttpMethodConstraint(value = "TRACE", emptyRoleSemantic = EmptyRoleSemantic.DENY))
    <security-constraint>
    <web-resource-collection>
    <url-pattern>...</url-pattern>
    <http-method-omission>TRACE</http-method-omission>
    </web-resource-collection>
    <auth-constraint>
    <role-name>Role1</role-name>
    </auth-constraint>
    </security-constraint>
    <security-constraint>
    <web-resource-collection>
    <url-pattern>...</url-pattern>
    <http-method>TRACE</http-method>
    </web-resource-collection>
    </auth-constraint>
    </security-constraint>

  • 映射@HttpConstraint和@HttpMethodConstraint到XML
    本节描述了从@HttpConstraint@HttpMethodConstraint注解值到它们auth-constraintuser-data-constraint表示的映射。这些注解为了表达在部署描述符中使用的auth-constraintuser-data-constraint元素的等价性共享一个公用模型。这个模型由下列3个元素组成:

    • emptyRoleSemantic
      当没有角色被命名在rolesAllowed中时,授权语义,PERMIT或者DENY应用。这个元素的默认值是PERMIT,并且DENY在联合使用一个非空rolesAllowed列表中并不被支持。
    • rolesAllowed
      这是一个包含已授权角色名字的列表。当这个列表为空,它的含义取决于emptyRoleSemantic的值。当包含在允许角色的列表中时,角色名字"*"没有特殊含义。这个元素的默认值是一个空列表。
    • TransportGuarantee
      无论是NONE或者CONFIDENTIAL,数据保护需求必须被请求到达的连接满足。这个元素等价于包含有对应值的transport-guarantee元素的user-data-constraint。这个元素的默认值是NONE。
      下列例子描绘了@HttpConstraint模型和web.xml中的auth-constrainttransport-guarantee元素之间的对应关系。
      CODE EXAMPLE 4-10 emptyRoleSemantic=PERMIT,rolesAllowed={},transportGuarantee=NONE
      没有限制
      CODE EXAMPLE 4-11 emptyRoleSemantic=PERMIT,rolesAllowed={},transportGuarantee=CONFIDENTIAL
      <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
      CODE EXAMPLE 4-12 emptyRoleSemantic=PERMIT,rolesAllowed={Role1},transportGuarantee=NONE
      <auth-constraint>
      <security-role-name>Role1</security-role-name>
      </auth-constraint>
      CODE EXAMPLE 4-13 emptyRoleSemantic=PERMIT,rolesAllowed={Role1},transportGuarantee=CONFIDENTIAL
      <auth-constraint>
      <security-role-name>Role1</security-role-name>
      </auth-constraint>
      <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
      CODE EXAMPLE 4-14 emptyRoleSemantic=DENY,rolesAllowed={},transportGuarantee=NONE
      <auth-constraint/>
      CODE EXAMPLE 4-15 emptyRoleSemantic=DENY,rolesAllowed={},transportGuarantee=CONFIDENTIAL
      <auth-constraint/>
      <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
  1. ServletRegistration.Dynamic的setServletSecurity
    setServletSecurity方法可以在ServletContextListener中被用来定义应用于为ServletRegistration定义的映射的安全约束。
    Collection<String> setServletSecurity(ServletSecurityElement arg)
    传递给serServletSecurityjavax.servlet.ServletSecurityElement参数类似@ServletSecurity注解的ServletSecurity接口的结构和模型。Mapping @ServletSecurity to security-constraint节中定义的映射关系类似于一个包含HttpConstraintElementHttpMethodConstraintElement值的ServletSecurityElement元素的映射,等价于security-constraint表示。
    setServletSecurity方法返回已经是部署描述符(因此不会被调用影响)中security-constraint元素的精确目标的URL模式的集合(可能为空)。
    如果ServletsContext(ServletRegistration从这里获取到)已经被初始化,那么这个方法将会抛出一个IllegalStateException
    当部署描述符中的一个security-constraint包含一个url-pattern,这个url-pattern是一个被ServletRegistration映射的模式的精确匹配,那么调用ServletRegistration之上的setServletSecurity一定不能影响Servlet容器在模式上的强制约束。
    有上述列出的异常以及包含何时Servlet类被@ServletSecurity注解,何时setServletSecurityServletRegistration上被调用,它会建立应用于registration的url-pattern的安全约束。

五、角色

一个安全角色是一个被应用开发者或者装配器定义的用户逻辑分组。当应用被部署,角色被一个开发者映射到运行时中的委托者或者组。
一个servlet容器为关联一个基于主体安全属性进来的请求的主体强制执行声明式或者编程式安全。
这可以在下述方式的任意一种中发生:

  1. 一个开发者已经在运行环境中把一个安全角色映射到一个用户组。调用主体所在的用户组从它们的安全属性中被检索。仅当主体属于安全角色已经被开发者映射到的用户组,主体才是在安全角色中。
  2. 一个开发者已经把一个安全角色映射到一个安全策略域中的一个主体名字。这种情况下,调用主体的主体名字从它们的安全属性中检索。仅当主体名与安全角色被映射到的主体名一样时,主体就在安全角色中。

六、认证

一个web客户端能够使用下列机制中的一种来给一个web服务器验证用户身份:

  • HTTP Basic Authentication
  • HTTP Digest Authentication
  • HTTPS Client Authentication
  • Form Based Authentication
  1. HTTP Basic Authentication
    HTTP Basic Authentication,基于用户名和密码,是定义在HTTP/1.0规范中的认证机制。一个web服务器请求一个web客户端来验证这个用户。作为请求的一部分,web服务器会传递一个字符串realm,用户会在这个里面被认证。web客户端从用户获取用户名和密码,然后把它们传递给web服务器。web服务器会在具体的realm中验证用户。
    Basic Authentication并不是一个安全认证协议。用户密码以简单的base64编码发送,并且目标服务器没有被验证。额外的保护能够缓解一些担心:一个安全传输机制(HTTPS), 或者网络级别的安全在一些部署场景下被应用。
  2. HTTP Digest Authentication
    像HTTP Basic Authentication,HTTP Digest Authentication基于一个用户名和密码验证一个用户。然而,不像HTTP Basic Authentication,HTTP Digest Authentication不会在网络上发送用户密码。在HTTP Digest Authentication中,客户端发送一个密码的单向加密哈希(以及额外的数据)。尽管密码不会在电缆上发送,但是HTTP Digest Authentication要求明文密码等价物对验证容器可用,以便容器能够验证收到的通过计算预期数字的验证器。Servlet容器应该支持HTTP_DIGEST验证。
  3. Form Based Authentication
    login screen的外观和感觉在使用web浏览器的内置验证机制时不能不同。本规范介绍了一个必须的form based authentication机制,它允许一个开发者控制登录界面的外观和感觉。
    web应用部署描述符包含了登录表单的错误页面的入口。登录表单必须包含用来输入用户名和密码的域。这些域必须分别命名为j_usernamej_password
    当一个用户尝试获取受保护的web资源,容器会检查用户的身份认证。如果用户被认证,并且拥有访问资源的权限,请求的web资源被激活,并且执行它的一个引用被返回。
    如果用户没有被认证,所有下述步骤会出现:
  4. 与安全约束相关的登录表单被发送给客户端,并且触发认证的URL路径被容器存储。
  5. 用户被让填写表单,包括用户名和密码。
  6. 客户端把表单以post方式发回给服务器。
  7. 容器尝试使用表单中的信息验证用户。
  8. 如果验证失败,使用发送或者重定向的方式返回一个错误页面,并且response的状态码被设置为200。
  9. 如果验证成功,认证用户的主体被检查,看它是否在获取资源的授权角色中。
  10. 如果用户被认证,客户端使用存储的URL路径被重定向到资源。
    发送给为通过验证的用户的错误页面包含失败的信息。

Form Based Authentication如Basic Authentication一样缺乏安全,因为用户密码被作为普通文本被发送,并且目标服务器没有被验证。额外的保护能够缓解一些担忧:一个安全传输机制(HTTPS), 或者网络级别的安全在一些部署场景下被应用。

  1. 表单登录注意事项
    基于表单的登录和基于URL的会话跟踪可能是有问题的实现。仅当会话被cookies或者SSL session信息维护的时候,基于表单的登录才应该被使用。
    为了进行适当的验证,登录表单的动作必须总是j_security_check。做这个限制以便登录表单无论是哪个资源都能正常工作,并且避免要求服务器指定表单之外的动作域。
    这是一个展示表单如何被编码到HTML页面中的例子:
    <form method="POST" action="j_security_check">
    <input type="text" name="j_username">
    <input type="password" name="j_password">
    </form>
    如果基于表单的登录由于一个HTTP请求被调用,原始请求的参数必须被容器保留,如果成功通过验证,它会把调用重定向到一个请求的资源。
    如果用户使用表单登录通过验证,并且已经创建一个HTTP会话,会话的超时或者非法导致用户在后续请求必须引发用户被重新认证的场景下被登出。登出的范围与认证的一样:比如,如果容器支持单点登录,如兼容Java EE技术的web容器,用户将需要和位于web容器的任何web应用重新认证。

  2. HTTPS Client Authentication

使用HTTPS(HTTP over SSL)的终端用户认证是一个很强的认证机制。这种机制需要客户端拥有一个Public Key Certificate(PKC)。当前PKCs在电商应用中很有用,并且在浏览器中的单点登录中也很有用。

  1. 其它容器认证机制
    Servlet容器应该提供一个公共接口,可以通过部署的应用的容器被用来集成和配置额外的HTTP消息层认证机制。这些接口应该被提供给缔约方使用,而不是给容器提供商(包括应用开发者,系统管理员,和系统集成者)。
    为了促进便携实现和额外容器认证机制的集成,推荐所有Servlet容器实现给容器提供的Java 认证SPI的Servlet Container Profile。SPI可以在这里下载:http://www.jcp.org/en/jsr/detail?id=196

七、认证信息的服务器跟踪

在运行时环境中角色被映射到的当前安全身份(如用户和组)是具体环境,而不是具体应用,它期望是:

  1. 做web应用部署的环境中的登录机制和策略。
  2. 能够使用相同的认证信息来对所有部署在同一个容器的应用代表一个主体。
  3. 仅当跨越了一个安全策略域边界,才需要用户的重新认证。
    因此,一个servlet容器被要求在容器级别跟踪认证信息(而不是web应用级别)。这允许对一个web应用已经认证的用户访问被其它拥有同样安全身份的容器管理的资源。

八、指定安全约束

安全约束是定义web内容保护的一个声明方式。一个安全约束与认证关联,用户数据与web资源上的HTTP操作关联。一个安全约束,在部署描述中被security-constration表示,由下列元素组成:

  • web资源集合(部署描述符中的web-resource-collection
  • 认证约束(部署描述符中的auth-constraint
  • 用户数据约束(部署描述符中的user-data-constraint
    HTTP操作和安全约束应用于的web资源被一个或者多个web资源集合识别。一个web资源集合由下列元素组成:
  • URL patterns(部署描述符中的url-pattern
  • HTTP方法(部署描述符中的http-methodhttp-method-omission元素)
    一个认证约束为认证和认证角色允许执行约束请求的名字建立一个要求。一个用户必须是允许执行约束请求的角色的一个成员。特殊的角色名字"*"是对定义在部署描述符中定义的所有角色名字的一个简称。一个没有命名角色的认证约束表明访问约束请求一定不能在任何环境下被允许。一个认证约束由下列元素组成:
  • 角色名字(部署描述符role-name
    一个用户数据约束建立一个必要条件:一个约束的请求在受保护传输层连接上被接收。所需保护的强度被传输保证的值定义。一个INTEGRAL的传输保证被用来为内容完整性建立一个必要条件,并且一个CONFIDENTIAL的传输保证被用来为加密简历一个必要条件。NONE的传输保证表明当在任何包含一个未受保护的连接上被接收时,容器必须接收约束的请求。一个用户数据约束有下列元素组成:
  • transport guarantee(部署描述符中的transport-guarantee
    如果没有认证约束应用于一个请求,容器必须接收请求,而不需要用户认证。如果没有用户数据约束应用于一个请求,当在任何包含一个未受保护的连接上被接收时,容器必须接收请求
  1. 联合约束
    为了联合约束的目的,当没有HTTP方法在集合中被命名,或者集合特地在一个被包含的http-method元素中特地命名了HTTP方法,或者集合包含一个或者更多http-method-omission元素,没有元素命名这个HTTP方法时,一个HTTP方法会在一个web-resource-collection中出现。
    当一个url-pattern和HTTP方法对在多个安全约束下出现在联合(比如在一个web-resource-collection中)中,这个约束(在pattern和方法上)通过联合单独的约束来定义。对相同pattern和方法出现的联合约束规则如下:
  • 命名角色或者通过名字"*"说明角色的认证约束的联合将会产生单个约束中角色名字的并集。一个不包含一个认证约束的安全约束将会结合命名或者暗示角色的认证约束来允许未认证约束。一个没有命名角色的认证约束的特殊例子将联合其它任何约束来重写它们的影响并且访问被阻止。
  • 应用于一个普通url-patternuser-data-constraintshttp-method的联合将会产生被单个约束接收的连接类型的并集。一个并不包含一个user-data-constraint的安全约束将会与其它user-data-constraint联合来让未保护的连接类型成为一个可接收的连接类型。
  1. 例子
    下列例子说明了约束的联合以及它们到一个应用约束表格的转换。假设一个部署描述符包含下列安全限制:
    <security-constraint>
    <web-resource-collection>
    <web-resource-name>preclued 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>SALEACLERK</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>
    这个假想部署描述符的转换将会产生下表中定义的约束:
    TABLE 安全约束表
url-pattern http-method permitted roles 支持的连接类型
/* 除了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 没有约束
  1. 处理请求
    当servlet容器接收一个请求,它将会使用Use of URL Paths中描述的算法来选择是请求URI的最佳匹配的url-pattern上定义的约束(如果有)。如果没有约束被选择,容器将会接收请求。否则容器将会决定请求的HTTP方法是否在选择的模式上被约束。如果不是,请求将会被接收。否则,请求必须在url-pattern上满足应用于HTTP方法的约束。下列两条规则必须满足将被接收的请求并且分发给关联servlet。
  2. 请求被接收连接上的特点必须满足至少一个被约束定义的支持连接类型。如果这条规则不被满足,容器将会拒绝请求并且会重定向到HTTPS端口。
  3. 请求的认证特点必须满足任何认证和通过约束定义的角色要求。如果这条规则由于访问被拒绝(通过一个认证约束没有命名角色)而不被满足,请求将会按照禁止状态被拒绝并且403(SC_FORBIDDEN)状态码将会被返回给用户。如果访问被限制允许角色并且请求还没有被认证,请求将会因为未认证被拒绝,并且401(SC_UNAUTHORIZED)状态码将会返回给原因认证。如果访问被限制允许角色并且请求的认证身份不是这些角色中任何一个的成员,请求将会因为禁止被拒绝,并且一个403(SC_FORBIDDEN)状态码将会被返回给用户。

九、默认策略

默认地,访问资源不需要被认证。当包含是请求URI最佳匹配的url-pattern的安全约束(如果有)在请求的HTTP方法上结合实施一个auth-constraint(命名角色)时,认证是必要的。相似地,一个受保护的传输并不必要,除非应用于请求上的安全约束在请求的HTTP方法上结合实施一个user-data-constraint(带一个受保护的transport-guarantee)。

十、登录和登出

把一个请求分发给servlet引擎时,容器建立请求的调用者身份。调用者身份在整个请求处理过程中保持不变,或者直到应用在request上成功调用authenticatelogin或者logout
请求处理期间被记录到一个应用中,由于可以通过调用request上的getRemoteUser或者getUserPrincipal,精确对应一个与请求关联的合法非空调用者身份。一个来自任意这些方法的null返回值表明调用者在请求处理时没有被记录进应用中。
容器可以穿件一个HTTP会话对象来跟踪登录状态。如果一个开发者创建了一个会话,同时一个用户没有被认证,那么容器会认证这个用户,登录之后对开发者代码的会话可见性必须是同一个会话对象,这个对象在登录出现之前被创建,以便没有会话信息的丢失。

翻译自 Java Servlet Specification
Version 3.0 Rev a
Author:Rajiv Mordani
Date: December 2010

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • 本章为部署描述符中Web容器支持详细描述Java Servlet 规范3.0版本要求。部署描述符在应用开发者,应用...
    Lucky_Micky阅读 1,936评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,015评论 11 349
  • Servlet Interface 是Java Servlet API的核心抽象。所有的servlets都直接或者...
    Lucky_Micky阅读 1,601评论 2 2
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,364评论 6 343