Web应用的前景是在不断的演进中的,它已经从最开始作为共享文档和信息的方式演化为业务管理的平台,而在这种应用中,许可和授权是一个关键的特征。Web的应用前景还在不断的演进中,而本文把关注放在面向群体的应用中,例如博可和维基。在这种应用中,由于作者希望有交流和反馈,所以授权不是非常严格的。有时,由于害怕识别,会造成失去一些人可能做出的贡献。但是,缺少授权就会带来诸如垃圾邮件这类的问题。这里有几条在Web上抽取的信息:
·我认为在维基上垃圾邮件是不可避免的。我建立了这个网站维基的一部分,把修改权限
平开放给每个人,以鼓励读者和来访者互相交流。但是,这已经是第二次了,一个发垃圾邮件的人把一堆到中国网站的链接放在这的网页里。(摘自X-Pollen)
·“致所有在维基上发垃圾邮件的人:从1-2-2005起,任何人要做任何操作,包括编辑或增加新页,都要由搜索引擎强制间隔十个小时。由于在这个网站上发的垃圾邮件在一分钟、最多一小时内就会被删除,所以,任何试图在这个网站上建立发垃圾邮件的机制都是徒劳的举动。(摘自C2 Wiki)”
很明显,垃圾邮件发送源必须被识别出来。大多数者类恶意的攻击发生数据匹配模式被识出来之后。一个可能的方法是人工而不是有计算机来停止这种攻击,很显然这是个挑战。通过图灵测试,按一个有名的计算机专家――阿兰。图灵命名的试验,可以确定机器能够实现类似人类操作的能力。者类测试中最有名的一个是CAPTCHA (an acronym for completely automated public Turing test to tell computers and humans apart)。这个测试常用来表明以个典型的情况:混乱或含义模糊的词,人很容易识别,但对于光学识别软件来讲却很困难。
图1是一个典型的CAPTCHA.
图1一个典型的CAPTCHA.
现在,大多数主要的服务提供商(Yahoo, Hotmail, Google)已经在他们的免费服务中使用CAPTCHA,用来作为区分垃圾邮件和虚假注册的手段。在本文中,我们要描述以下在我们的Web应用中加入基于CAPTCHA授权的方法。
首先,我们快速浏览以下J2EE中Web应用的安全模型。
J2EE安全模型
在Java开发中,安全性始终是一个最受关注的领域。毫无疑问,J2EE在构建安全的应用时,采用了同样的原理和健壮的框架。在J2EE中,安全性是一个很大的题目,在这里是不可能叙述细节的。在这方面有好多好的资源。我极力推荐团队和个人花些时间来熟悉这些概念。在这力,我只能极概括的叙述一些最关键的概念。
关键概念
在J2EE应用中,安全性必须采用声明或编程的话方法。就象名字中暗示的,当采用声明方法时,开发者在应用软件代码的外部定义用于应用的安全性约束。这些声明用部署描述符的形式来建造(web.xml, ejb-jar.xml),并由容器的运行环境来保证它的强制执行。声明的方式容许开发者:
·能够实现基于身份的对资源存取的约束(例如:/admin/* 只能容许有管理员身份的人来操作)
·能够实现对某些URL的存取只能用某种协议的约束(例如:“/customer/*”只能通过HTTPS来访问)
·能够实现基于身份的对某些服务存取的约束(例如:可以限定SiteShutdownServlet只能由具有“god”身份的人来操作)
·能够实现当用户要存取某些受限资源但用户还没有登录到系统的时候,自动重定向到登录页面的功能.而编程的方法能提供查询和调用安全设施的机制,而开发者必须实现这些机制。这个方法的特点是:
·检索出与当前用户相关联的部分:HttpServletRequest.getUserPrincipal or EJBContext.getCallerPrincipal
·查询用户是否具有某种特定的身份:HttpServletRequest.isUserInRole(String role) or EJBContext.isCallerInRole(String role)
这两种方法都有它的局限性,并且是能互相补充的。
Web应用的声明安全的方法
Web应用的声明安全的方法本质上是一种被动的方法。这意味者只有在刚开始访问受保护资源的用户,如果他们没有被受权,才会被重定向到登录页面。如果这个用户已经被授权并有适当的权限,他们就能访问这些资源。
这类方法中有一个最常用的方法是基于规则的受权。应用部署描述符web.xml分两个部分描述了在这个方法中需要的所有元素。
第一部分是适用于整个应用的。它要鉴别出:
·在登录中需要使用的方法。J2EE支持BASIC,DIGEST,FORM,或CERT等几种授权机制。
·用于基于规则受权的登录和错误的页面
·能在应用中使用的所有身份的超集
图2表明了第一部分的关键元素和它们之间的关系
图2 第一部分的关键元素和它们之间的关系
第二部分说明了资源方面的约束。部署描述符可以包含零个或多个类似于下面的声明:
·需要保护的站点。这可以在web-resource-collection内使用url-pattern来配置。
·能够存取资源的身份的集合(auth-constraint)。它通常是第一部分定义的身份集合的一个子集。
·与某个资源相关的传输的保证(user-data-constraint)。
图3表明了第二部分的关键元素和它们之间的关系
图3 第二部分的关键元素和它们之间的关系
现在,我们看一个简单的例子web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<!-- constrain a section of the site -->
<security-constraint>
<display-name>Anonymous Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/security/protected/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>anonymous</role-name>
</auth-constraint>
</security-constraint>
<!-- Default login configuration uses form-based authentication -->
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Anonymous Form-Based Authentication Area</realm-name>
<form-login-config>
<form-login-page>/security/protected/login.jsp</form-login-page>
<form-error-page>/security/protected/error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>anonymous</role-name>
</security-role>
<!-- The Usual Welcome File List -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
这个片断包含了这样一些内容:
·所有保存在/security/protected目录下的资源(JSP网页,SERVLETS)都要受容器的保护
·Anonymous是惟一的可访问这些资源的用户
·这个容器只接受HTTP 方式的GET 和POST请求
·受保护的资源只能通过常规的HTTP连接方式提供服务
·使用基于规则的授权;security/protected/login.jsp and /security/protected/error.jsp 分别作为登录和出错的页面
在写好安全部分后,就需要写登录和出错的页面。由于把每个会话与一个CAPTCHA或标识相关联,所有login.jsp 包含到TokenServlet的请求。
login.jsp的一部分:
.....
.....
<%-- Generates and associates a CAPTCHA --%>
<img src="/servlet/AuthToken" alt="Your authentication token"/>
<%-- The form login page --%>
<form method="POST" action='<%= response.encodeURL("j_security_check") %>' >
<table border="0" cellspacing="5">
<input type="hidden" name="j_username" value="<%= session.getId() %>">
<tr>
<th align="right">Challenge:</th>
<td align="left"><input type="password" name="j_password"></td>
</tr>
<tr>
<td align="right"><input type="submit" value="Log In"></td>
<td align="left"><input type="reset"></td>
</tr>
</table>
</form>
.....
.....
登录页面使用基于规则的安全方法,并把数据提交给j_security_check。j_username输入域被隐藏起来,默认值是用户会话的ID。另一个域,j_password是用户输入标识的地方。
出错页面是相当简单的。它只是提示灾害授权过程中发生乐和错误,还提供了以个到登录页面的连接。
产生新会话的惟一的标识
下面,需要提供与新会话相关联的标识符的方法。
为支持产生多个标识,我们采用抽象工厂模式。jw.token.factory.TokenFactory是抽象工厂模式,根据给定的参数,初始化一个具体的标识符产生工厂,并将其返回。如果没有要求一个特定的标识符产生工厂,就会返回一个默认的实现。Resources里有些分布式的可用的标识符产生工厂可以下载。第一个是我的业余练习jw.token.factory.SimpleTokenFactory。第二个是jw.token.Token,式由Jcaptcha项目提供的一个更成熟的实现。可以有getToken()来调用。标识符对象是一个用于CAPTCHAs的容器,可以通过在调用getTokenImage()时被当作一幅图像来渲染。
图5描述了标识符工厂对象模型
图9 login()的顺序图
与容器的安全设施整合
现在考虑把各个部分与容器的安全设施相整合。这是一个与服务相关的步骤。Tomcat为每个Web 应用管理一个配置文件。这个文件命名为.xml,放在
%lt;?xml version='1.0' encoding='utf-8'?>
%lt;Context debug="9" docBase="d:/work/captcha-login/web" path="/clogin">
%lt;Realm className="org.apache.catalina.realm.JAASRealm" appName="clogin" debug="99" roleClassNames="jw.jaas.AnonymousPrincipal" userClassNames="jw.jaas.AnonymousPrincipal"/>
%lt;/Context>
此外,我们要求JAAS配置直接与应用对应的登录模块。
JAAS配置文件:
clogin {
jw.jaas.AnonymousLoginModule required debug=true;
};
图10这种应用的一种屏幕显示
必要的准备
为了构造和测试这个应用,我们需要Web container version 5.0或更高的版本,还有Ant build environment version 1.5或更高的版本。这些可以从Apache下载和安装。一旦有了这些准备,我们就可以安下面的步骤来构造和部署应用了。
安装和测试
·下载并解压缩jw-0307-captcha.zip到一个目录(如:d:\captcha)。解压缩出来的文件会包括源代码、库文件、Web应用和编译脚本。
·转到文件被解压缩到的目录,编辑文件setAntEnv.cmd。象文件名暗示的那样,这个文件包含开发环境启动时所需要的变量。编辑变量ANT_HOME和JAVA_HOME,使其指向正确的位置。所有其它的部分都是从这两个变量导出的,因此不需要改动。
·还是在这个目录下,编辑文件ant.developer.properties。这个文件包含影响应用编译采用的方法的部分。文件中的大部分都有一个有意义的默认值,你只需要设置build.home和server.home。
·现在,打开命令行窗口,并转到这个目录(d:\captcha),并执行setAntEnv.cmd批处理脚本。
·输入ant compile jar deploy来编译并部署这个应用。Ant脚本首先创建需要的目录,编译并安全模块代码,并打包为JAR文件。最后部署它。
·通过输入ant start命令来启动应用的服务端。Tomcat应该在以个独立的窗口启动并运行。
·打开浏览器,让它指向http://localhost:8080/clogin (clogin是在ant.developer.properties 中配置的application.name属性)。
·在测试完毕后,你可以通过关闭Tomact窗口的方式来停止服务。
无论什么时候改变了ant.developer.properties中的属性,都要重新编译,以保证所有的属性的依赖都是正确的。例如,如果你使用了out-of-box配置,标示符服务器将使用简单的标示符工厂。你也可以把文件ant.developer.properties中的captcha.token.factory的值改为jw.token.factory.JCaptchaTokenFactory来做更复杂的测试。运行ant clean-all deploy来传播变化。启动服务端并测试应用。
调试
根据你的环境的不同,应用在启动的时候可能会失败。编译脚本已经部署了一个用于Tomcat配置的的名为log4j的文件。你可以打开
结论
在这篇文章中,我们浏览了J2EE Web应用的声明安全模型,还有扩展它来使用JAAS登录模块的方法。我们扩展了Tomcat的J2EE安全设施以支持一种用户定义的授权机制。这个授权机制是作为一个JAAS登录模块实现的,并在较弱的用户授权中使用了CAPTCHSs。对于某种应用领域,它能确定远端用户是一个人。使用容器提供的安全机制,我们可以很容易的确保应用的安全而不用更改任何代码。
应该注意到,CAPTCHAa既可以产生对用户有用的结果,也可以产生无用的结果。当开发者在选择授权机制的时候应该注意到这个问题。
关于作者
Anand Raman作为技术方面的合作者为Sapient在德里以外的地方工作。在过去的五年中一直从事JAVA和J2EE相关的技术工作。追踪J2EE的复杂性是他最感兴趣的。
版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接
原文:http://www.javaworld.com/
译文:http://www.matrix.org.cn/