一. 身份验证和授权
认证是检验某人真正是他/她自称的那个人的过 程。在一个Servlet/JSP应用程序中,身份验证一般通过 检查用户名密码是否正确。授权是检查该级别的用户是 否具备访问权限。它适用于包括多个区域的应用程序, 其中用户可以利用这个应用程序的部分模块,但是其他 模块就没有权限。例如,一个在线商店可被划分成的一 般部分(用于一般公众浏览和搜索产品)、买家部分 (注册用户下订单)和后台管理部分(适用于管理 员)。这三者中,后台管理部分需要访问的最高权限。 管理员用户不仅需要进行身份认证,他们还需要获得后 台管理部分的权限。
访问级别通常被称为角色。在部署一个Servlet/JSP 应用程序时可以方便地通过模块分类和配置,使得每个 模块只有特定角色才能访问。这是通过在部署中声明安 全约束描述符完成的。换句话说,就是声明式安全。在 这个范围的另一端,内容限制是通过编程实现检验用户 名和密码与数据库中存储的用户名和密码对是否匹配。
大多数Servlet和JSP应用程序的身份验证和授权首 先要验证用户名和密码与数据库表是否一致。一旦验证 成功,可检查另一个授权在同一个表中存储的用户名和 密码的表或字段。使用声明式安全可让您的编程更简 洁,因为Servlet/JSP容器负责身份验证和授权过程。此 外,Servlet/JSP容器配置数据库来验证你已经在应用程 序中使用。最重要的是,使用声明式身份验证的用户名 和密码可在被发送到服务器之前由浏览器对其加密后再 发送给服务器。声明式安全的缺点是,支持数据加密的 身份验证方法只能使用一个默认登录对话框,不能对界 面和操作进行个性化定制。这个原因就足以让人放弃声 明式安全。声明性安全的唯一方法是允许使用一个自定 义的HTML表单,不幸的是数据传输不加密。
Web应用程序的某些部分,如管理模块,是不面向 客户的,所以登录表单的外观是没有关联的。在这种情 况下,声明式安全仍然被使用。
声明式安全有趣的部分当然就是安全约束不编入 Servlet了。相反,它们在应用程序部署时声明在部署描 述符中。因此,它具有相当大的灵活性来确定用户和角 色对访问的应用程序或部分模块的权限。
要使用声明式安全,首先定义用户和角色。根据您 所使用的容器,您可以将用户和角色信息存储在一个文 件或数据库表中,然后,您对应用程序中的资源或集合 施加约束。
现在,您如何不通过编程来验证用户?你会发现后 面的答案在于HTTP而不是Servlet规范。
二. 指定用户和角色
每一个兼容Servlet/JSP容器必须提供一个定义用户 和角色的方法。如果你使用Tomcat,可以通过编辑conf 目录中的Tomcat-user.xml来创建用户和角色。tomcat-users.xml
tomcat-users.xml 文件
<?xml version=‘1.0‘ encoding=‘utf-8‘?> <tomcat-users> <role rolename="manager"/> <role rolename="member"/> <user username="tom" password="secret" roles="manager,memb er"/> <user username="jerry" password="secret" roles="member"/> </tomcat-users>
tomcat-users.xml文件是一个xml文档的根元素 tomcat-user。在里面是role和user元素。role元素定义角 色,user元素定义用户。role元素有rolename属性指定角 色名。user元素具有username、password和role属性。 sername属性指定用户名,password属性指定密码,role 属性指定角色或用户属于的角色。
tomcat-users.xml文件声明了两个角色 (经理和成员)和两个用户(tom和jerry)。用户tom是 一个成员和经理的角色,而杰瑞只属于成员角色。很明 显,汤姆比杰瑞具有接入更多应用的权限。
Tomcat还支持通过数据库表来匹配角色和用户。 你可以配置Tomcat使用JDBC来验证用户身份。
二. 实施安全约束
你已经学会通过把静态资源和JSP页面放在WEBINF目录下来隐藏起来。资源放置在这里不能直接通过 输入URL访问,但仍然可以从一个Servlet或JSP页面进 入。虽然这种方法简单明了,缺点是资源隐藏在这里永 远是隐藏的,没有办法直接访问。如果你只是简单地想 保护资源不被未经授权的用户访问,你可以把它们放在 应用程序目录下的一个目录中,在部署描述符中声明一 个安全约束。
security-constraint元素指定一个资源集合和角色或 角色可以访问的资源。这个元素有两个子元素:webresource-collection和auth-constraint。
web-resource-collection元素指定一组资源,可以包 括web-resource-name、description、url-pattern、httpmethod和http-method-ommission等子元素。
web-resource-collection元素可以有多个url模式子元 素,每一个都是指一个URL正则表达式用于指定安全约 束。您可以使用星号的url模式元素来引用一个特定资 源类型(例如, * . jsp)或所有资源目录(比如/ *或/ jsp / *)。然而,你不能同时指定两个,例如,在一个 特定的目录中指定一个特定类型。因此,下面的URL表 达式指定jsp目录下的所有JSP页面是无效的:/ JSP / * . JSP。相反,使用/ jsp / * ,也将限制任何在jsp目录下的 非JSP页面。
http-method元素为封闭的安全约束的应用命名了一 个http方法。例如,一个web-resource- collection元素以 GET http-method命名,表明该web-resource-collection元 素仅适用于HTTP GET方法。包含资源集合的安全约束 不能防止其他HTTP方法,如PUT方法。没有httpmethod元素表示安全约束限制了所有HTTP访问方法。 你可以在同一个web-resource-collection中拥有多个 httpmethod元素。
http-method-omission元素指定一个不包含HTTP方 法的安全约束。因此,指定< http-methodomission > GET< / http-method-omission >表示限制除了GET外的所 有HTTP方法。
http-method元素和http-method-omission元素不能出 现在相同的web-resource-collection元素里。
在部署描述符中可以有多个security-constraint元 素。如果security-constraint元素没有auth-constraint元 素,那么这个资源集合是不被保护的。此外,如果你指 定的角色没有在容器中定义,那么没有人能够直接访问 这个资源集合。然而,你仍然可以通过一个servlet或 JSP页面转向集合中的资源。
这里有个例子,下面的xml文件的securityconstraint元素限制所有JSP页面的访问权限。由于authconstraint不包含rolename元素,因此无法通过它们的 urls直接访问这个资源
防止访问特定目录下的资源
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ? http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" > <!-- restricts access to JSP pages --> <security-constraint> <web-resource-collection> <web-resource-name>JSP pages</web-resource-name> <url-pattern>*.jsp</url-pattern> </web-resource-collection> <!-- must have auth-constraint, otherwise the specified web resources will not be restricted --> <auth-constraint/> </security-constraint> </web-app>
servlet容器将发送一个HTTP 403错误:访问所请求 的资源已经被否认。
现在让我们看看如何对用户进行身份验证和授权。