servlet 安全约束机制

一般说来,servlet 会部署到 internet 上,因此需要一些安全性的考虑。你可以制定 servlet 的安全模式,例如角色、访问控制、鉴权等。这些都可以用 annotation 或 web.xml 进行配置。

@ServletSecurity 定义了安全约束,它可以添加在 servlet 实现类上,这样对 servlet 中的所有方法都生效,也可以单独添加在某个 doXXX 方法上,这样只针对这个方法有效。容器会强制调整 doXXX 方法被指定角色的用户调用:

  1. @WebServlet("/account")  
  2. @ServletSecurity(  
  3.   value=@HttpConstraint(rolesAllowed = {"R1"}),  
  4.   httpMethodConstraints={  
  5.     @HttpMethodConstraint(value="GET",   
  6.                           rolesAllowed="R2"),  
  7.     @HttpMethodConstraint(value="POST",   
  8.                           rolesAllowed={"R3", "R4"})  
  9.   }  
  10. )  
  11. public class AccountServlet   
  12.              extends javax.servlet.http.HttpServlet {  
  13.   //. . .  
  14. }  

在上面的代码段中,@HttpMethodConstraint 定义了 doGet 方法只能被角色为 R2 的用户调用,doPost 方法只能被角色为 R3 或 R4 的用户调用。@HttpConstraint 定义了其它的所有方法都能被角色为 R1 的用户调用。角色与用户映射容器的角色和用户。

安全约束也可以使用 web.xml 中的 <security-constraint> 元素来定义。在这个元素中,使用 <web-resource-collection> 元素来指定 HTTP 操作和 web 资源, 元素     <auth-constraint> 用来指定可以访问资源的角色,<user-data-constraint> 元素中使用 <transport-guarantee> 元素来指定客户端和服务器端的数据应该怎样被保护:

  1. <security-constraint>  
  2.   <web-resource-collection>  
  3.     <url-pattern>/account/*</url-pattern>  
  4.     <http-method>GET</http-method>  
  5.   </web-resource-collection>  
  6.   
  7.   <auth-constraint>  
  8.     <role-name>manager</role-name>  
  9.   </auth-constraint>  
  10.   
  11.   <user-data-constraint>  
  12.     <transport-guarantee>INTEGRITY</transport-guarantee>  
  13.   </user-data-constraint>  
  14. </security-constraint>  



上面这段部署描述符表示:在 /account/* URL 上使用 GET 请求将会受到保护,访问的用户必须是 manager 角色,并且需要数据完整性。所有 GET 之外的其它 HTTP 请求都不会受到保护。 如果在 <security-constraint> 中没有明确指定 HTTP 方法的约束,那么默认所有的 HTTP 方法都会受到保护:

  1. <security-constraint>  
  2.   <web-resource-collection>  
  3.     <url-pattern>/account/*</url-pattern>  
  4.   </web-resource-collection>  
  5.   
  6.   . . .  
  7. </security-constraint>  

上面这段配置表示所有访问 /account/* URL 的 HTTP 方法都将受到保护。

从 Servlet 3.1 开始,规定了没有列入 <security-constraint> 中的 HTTP 方法称为“未被覆盖的方法”(uncovered,意思是在 security-constraint 中没有覆盖到此方法),并且在 <security-constraint> 中至少需要指定一个 <http-method> 元素:

  1. <security-constraint>  
  2.   <web-resource-collection>  
  3.     <url-pattern>/account/*</url-pattern>  
  4.     <http-method>GET</http-method>  
  5.   </web-resource-collection>  
  6.   . . .  
  7. </security-constraint>  

上面的配置中,只有 GET 方法会受到保护,所有其它的 HTTP 方法,比如 PUT、POST 都是“未被覆盖的方法”。

在 <http-method-omission> 元素中可以指定哪些 HTTP 方法不受保护:

  1. <security-constraint>  
  2.   <web-resource-collection>  
  3.     <url-pattern>/account/*</url-pattern>  
  4.     <http-method-omission>GET</http-method-omission>  
  5.   </web-resource-collection>  
  6.   
  7.   . . .  
  8. </security-constraint>  



在上面的例子中,只有 HTTP GET 方法将不受保护,其它的 HTTP 方法将会受到保护。

<deny-uncovered-http-methods> 元素是 Servlet 3.1 中新增加的元素,用于阻止使用“未被覆盖的方法”进行访问。如果使用这个被阻止的 HTTP 方法进行访问,那么将会收到 403(SC_FORBIDDEN)错误状态码:

  1. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
  2.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee   
  4.            http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"  
  5.          version="3.1">  
  6.   <deny-uncovered-http-methods/>  
  7.   <web-resource-collection>  
  8.     <url-pattern>/account/*</url-pattern>  
  9.     <http-method>GET</http-method>  
  10.   </web-resource-collection>  
  11.   . . .  
  12. </web-app>  



在上面的例子中,除了 HTTP GET 方法可以安全访问之外,其它所有的 HTTP 方法访问将会返回 403 错误码。

@RolesAllowed、@DenyAll、@PermitAll、和 @TransportProtected是用来进行安全配置的 Annotation:

  1. @RolesAllowed("R2")  
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) {  
  3.   //. . .  
  4. }  



如果同样的 annotation 被添加到类和方法上,那么方法级别的配置将覆盖类级别的配置。

Servlet 3.1 包含了两个预定义的角色:

    * - 表示任意已定义的角色
    ** - 表示某个角色下的任意认证用户

这将允许你在更高的级别设置安全约束,而不仅仅只是针对某个角色。

同一个声明上,最多只能使用一个 @RolesAllowed、@DenyAll 或 @PermitAll 注释。@TransportProtected 可以和 @RolesAllowed 或 @PermitAll 进行组合。

可以将 Servlet 进行配置与基本 HTTP,HTTP Digest,HTTPS 客户端、或 form 表单进行权限认证

  1. <form method="POST" action="j_security_check">  
  2.   <input type="text" name="j_username">  
  3.   <input type="password" name="j_password" autocomplete="off">  
  4.   <input type="button" value="submit">  
  5. </form>  



上面的例子演示了如何使用 form-based 的方法进行验证。登陆表单必须包含用户名和密码,并且用户名和密码字段的名称必须分别是“j_username”和“j_password”,form 表单提交的 action 必须是 “j_security_check”。

Servlet 3.1 需要在密码字段上添加 autocomplete="off",用于进一步加强 form 表单的安全性。

HttpServletRequest 也提供了 login、logout 和 authenticate 方法,方便使用编码的方式来进行权限验证。

login() 方法将验证用户名和密码是否匹配在 ServletContext 中的配置(依赖 web 容器进行配置)的用户名密码。这将保证 getUserPrincipal、getRemoteUser、和 getAuthType 返回正确的值,使用 HttpServletRequest 提供的 login 方法可以取代上面使用的 form-based 验证。

authenticate() 方法将使用 ServletContext 的容器登陆机制来验证用户发起的这次请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值