互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki89 忆一下2EE安全,基本上就是对资源设置约束,否则这些资源就可以随意地被访问。在这个例子 中,这些资源就是准备借助DWR进行远程访问的类。 容器管理安全的工作方式是首先创建角色。从理论上来讲,角色映射到一类用户。例如,思 考一下,普通用户和管理用户的异同。然后,列出指定的用户,告诉这个用户他或者她所属的角 色(即某个规则集合)例如,在实际限制资源的访问时,如果希望只有管理用户才能访问以/ admin 开头的URL,那么可以告诉容器只有某些角色的用户才能够访问这个URL。你不必列出每个用户 只需列出角色。 因此,安全配置文件首先要列出角色和用户。这一点,每个容器都不相同。不过,在 Tomcat 中通过在 tomcat- users.xm1中添加条目可以非常简单地完成角色和用户的配置。在 ${ TOMCAT}/ conf目录中可以找到这个文件。代码清单5-3列出了DWki中使用的 tomcat-users. xml 代码清单5-3 tomcat- users.xm1配置文件 xml version=1.0 encoding=utf-8?> <tomcat-users> cr /> <user username="wiki"password=" wiki" roles= wiki user </tomcat-users> 在这个例子中,由于我们仅仅讨论特定用户是否注册,因此实际上只需要一个角色,即 wiki user。接着,配置一个用户 wiki,可以看到该用户的密码。还可以看到<user>元素有 一个 roles属性,它定义了用户所属的角色或角色列表。角色列表是一个以逗号分隔的列表,其 中的角色名对应到<xo1e>元素的 rolename属性(这里可能有许多角色)。需要做的就这些!现 在 Tomcat就能感知到应用程序的用户和角色了 目前,实际上是在应用级别,即在web.xm1文件中使用这个配置。因此,接下来我们继续看 它是如何配合起来的。 容器管理(J2EE)安全是一个庞大的主题,因此这里不会讲述它的全部内容。由于它的机制本 质上比较简单,因此,坦白地说,主要的内容并不多。不过,由于容器/应用服务器可自由地在这个 基本机制之上提供增值特性,所以这种安全机制受到了越来越多的关注。一个很流行的例子就是借 助于LDAP目录实现用户信息存储。如果希望更深入地了解容器管理安全,给你推荐一些有用的网 A:http://java.sun.com/j2ee/tutorial/l_3-fcs/doc/security.htmlwww.ibm.com/developerworks/websphere techjournal/0303 barcia/ barcia. html以及htp/ mcat. apache. org/tomcat-60 doc/realm-howto html,请记 住,每种应用服务器都会有些不同,因此请使用自己喜欢的搜索引擎来搜索相关信息 web xml 配置了用户和角色之后,最后一步是配置应用程序本身,限制对受保护资源的访问。请牢牢
5.2 剖析 DWiki 89 忆一下J2EE安全,基本上就是对资源设置约束,否则这些资源就可以随意地被访问。在这个例子 中,这些资源就是准备借助DWR进行远程访问的类。 容器管理安全的工作方式是首先创建角色。从理论上来讲,角色映射到一类用户。例如,思 考一下,普通用户和管理用户的异同。然后,列出指定的用户,告诉这个用户他或者她所属的角 色(即某个规则集合)。例如,在实际限制资源的访问时,如果希望只有管理用户才能访问以/admin 开头的URL,那么可以告诉容器只有某些角色的用户才能够访问这个URL。你不必列出每个用户, 只需列出角色。 因此,安全配置文件首先要列出角色和用户。这一点,每个容器都不相同。不过,在Tomcat 中通过在tomcat-users.xml中添加条目可以非常简单地完成角色和用户的配置。在 ${TOMCAT}/ conf 目录中可以找到这个文件。代码清单 5-3 列出了 DWiki 中使用的 tomcat-users.xml。 代码清单5-3 tomcat-users.xml配置文件 在这个例子中,由于我们仅仅讨论特定用户是否注册,因此实际上只需要一个角色,即 dwiki_user。接着,配置一个用户dwiki,可以看到该用户的密码。还可以看到<user>元素有 一个roles属性,它定义了用户所属的角色或角色列表。角色列表是一个以逗号分隔的列表,其 中的角色名对应到<role>元素的rolename属性(这里可能有许多角色)。需要做的就这些!现 在Tomcat就能感知到应用程序的用户和角色了。 目前,实际上是在应用级别,即在web.xml文件中使用这个配置。因此,接下来我们继续看 它是如何配合起来的。 容器管理(J2EE)安全是一个庞大的主题,因此这里不会讲述它的全部内容。由于它的机制本 质上比较简单,因此,坦白地说,主要的内容并不多。不过,由于容器/应用服务器可自由地在这个 基本机制之上提供增值特性,所以这种安全机制受到了越来越多的关注。一个很流行的例子就是借 助于LDAP目录实现用户信息存储。如果希望更深入地了解容器管理安全,给你推荐一些有用的网 页:http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Security.html、www.ibm.com/developerworks/websphere/ techjournal/0303_barcia/barcia.html以及http://tomcat.apache.org/tomcat- 6.0-doc/realm-howto.html。请记 住,每种应用服务器都会有些不同,因此请使用自己喜欢的搜索引擎来搜索相关信息。 2. web.xml 配置了用户和角色之后,最后一步是配置应用程序本身,限制对受保护资源的访问。请牢牢
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki90 记住,服务器的工作就是提供服务。如果没有采取任何方法配置,那么特定的资源是不被保护的 (用2EE安全的术语来说,就是不受限制的)。限制对资源的访问只需要在标准的web.xm1文件中 加入某些项,如代码清单5-4所示。 代码清单5-4DWki的web.xm1文件 <?xml version="1.encoding="IS0-8859-1"7> web-appid=dwiki"version=2.4"xmins="http://java.suncom/xml/ns/j2ee xmlns:xsi="http://www.w3.org/2001/xmlschema-instance xsi:schemalocation=http://java.sun.com/xml/ns/j2ee http://java.suncom/xml/ns/j2ee/web-app_2_4.xsd> <display-name>Wiki</display-name> <listener> <listener-clas com.apress.dwrprojects. dw1k1 Dwik1ContextLlstene </listener -> servlet> <servlet-name>dwr-invoker</servlet-name> servlet-class>ukItd getahead, dwr. DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> aram-value>true</param-value </init-param> <param-name>crossDomainSess curity</param-name> param-value>false</param-value> init </servlet> <servlet-mapping <servlet-name>dwr-invoker</servlet-name> url-pattern/dwr/*</url-pattern </servlet-mapping
5.2 剖析 DWiki 90 记住,服务器的工作就是提供服务。如果没有采取任何方法配置,那么特定的资源是不被保护的 (用J2EE安全的术语来说,就是不受限制的)。限制对资源的访问只需要在标准的web.xml文件中 加入某些项,如代码清单5-4所示。 代码清单5-4 DWiki的web.xml文件
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki91 login-config kauth-method> FORM</auth-method <form-login-configy jsp</form-login-pag <form-error-page>/login. jsp?login bad=true</form-error-page </form-login-config> <security-constraint> <web- resource-collection> url-pattern>/loginOk jsp</url-pattcrn> <http-method>get</http-method> </web-resource-collection> kauth-constraint. <role-name>wiki user</role-name> </auth-constraint> </security-constraint> <security-role> </security-role> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> welcome-file>index. jsp</welcome-filex </welcome- file-list) </web-app> 我们最关心的当然是< servlet- mapping>。一会儿再讨论<1ogin- config>,现在先介绍 < security- constraint>。它定义一个需要限制的资源。这里,我们声明 loginok.jsp需要特 别的保护。接着,声明仅有GET方法需要保护。显然这并不是最安全的,但是它足以满足需求(由于 只是为已知用户开发登录机制,因此没有必要过于关注资源的保护问题)。在 < security- constraint>元素中还有一个<auth- constraint>元素,这是声明这个受限资源只能 被归属 wiki user角色的用户访问 < security- constraint>之后是< security-ro1e>元素。和 tomcat- users.xm1中的定义 样,这个元素用于声明某个特定的角色可以在这个Web应用程序中使用。在此我们只配置了一个 角色,因此仅需要一个< security-ro1e>元素。不过,如果需要,当然可以配置多个。 现在回到<1ogin- config>元素。当一个客户请求受限资源时,将会发生什么呢?如果只是 简单地拒绝请求,并没什么了不起,不是吗?是的,还会做一些其他的事情,<1ogin- config> 元素告诉容器在这些情况下该如何处理。更明确的方法是,由<auth- method>元素定义处理方 法。这里有几个选择,其中之一就是 BASIC,它会导致浏览器弹出对话框要求用户输入用户名和 密码(这个是与浏览器相关的)。也可以使用 CLIENT CERT,要求客户端发送一个服务器可以识 别的数字签名。还可以是 DIGEST,类似于 BASIC,不过需要服务器端做额外的配置,以支持MD5
5.2 剖析 DWiki 91 我们最关心的当然是<servlet-mapping>。一会儿再讨论<login-config>,现在先介绍 <security- constraint>。它定义一个需要限制的资源。这里,我们声明loginOk.jsp需要特 别的保护。接着,声明仅有GET方法需要保护。显然这并不是最安全的,但是它足以满足需求(由于 只 是 为 已 知 用 户 开 发 登 录 机 制 , 因 此 没 有 必 要 过 于 关 注 资 源 的 保 护 问 题 )。 在 <security-constraint>元素中还有一个<auth-constraint>元素,这是声明这个受限资源只能 被归属dwiki_user角色的用户访问。 <security-constraint>之后是<security-role>元素。和tomcat-users.xml中的定义一 样,这个元素用于声明某个特定的角色可以在这个Web应用程序中使用。在此我们只配置了一个 角色,因此仅需要一个<security-role>元素。不过,如果需要,当然可以配置多个。 现在回到<login-config>元素。当一个客户请求受限资源时,将会发生什么呢?如果只是 简单地拒绝请求,并没什么了不起,不是吗?是的,还会做一些其他的事情,<login-config> 元素告诉容器在这些情况下该如何处理。更明确的方法是,由<auth-method>元素定义处理方 法。这里有几个选择,其中之一就是BASIC,它会导致浏览器弹出对话框要求用户输入用户名和 密码(这个是与浏览器相关的)。也可以使用CLIENT_CERT,要求客户端发送一个服务器可以识 别的数字签名。还可以是DIGEST,类似于BASIC,不过需要服务器端做额外的配置,以支持MD5
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki9 加密。最后一种选择,可能也是最常用的,就是我们这里用的FORM。 FORM验证方法会导致容器重定向到某个登录页面,可以在<form-1ogin-page>元素中配置这 个登录页面,在这个应用程序中配置的页面是1ogin.jsp。当然,并没规则说要使用什么样的JSP 页面(事实上,甚至可以不使用JSP页面,可以是普通的HIML页面,或者如果正在使用 Struts并 且配置适当,则可以是一个 Structs i动作)。 J2EE安全的替代机制 这里讨论的容器管理安全机制并不是唯一的选择。 acegi是另一种可行的选择,它是一个 流行的安全框架,提供了J2EE安全所没有的许多功能,也是可供大量用户访问的比较健壮的 基础架构。可以将 Acegi集成到DWR中(虽然目前并没有正式开始支持这种集成)。DwWR文档 出了一个链接,指向一篇详细讲述 Acegi与DWR集成的文章,如果有兴趣的话,可以看 (这里就不再进一步讨论这个主题了) 由以上内容可知,事件的顺序是这样的,客户端请求受限资源,在本例中就是1 ogino.jsp 文件。容器发现该资源被限制,便把客户端重定向到事先配置的登录页面1ogin.jsp。后面将看 到,这个页面显示了一个特殊的表单以供用户输入自己的用户名和密码。这个表单会被提交给 个特殊的 servlet,该 servlet使用 tomcat- users.xm1中的配置来验证这些信息。假设这些信息是 有效的,容器会返回客户请求的资源1 ogino.jsp,用户便能有效登录。如果这些信息无效, 容器会将客户端重定向到<form-eror-page>元素指定的页面,这个页面也是ogin.jsp,不 过这次页面中会以红色显示出一条消息,提示信息无效(请注意,<form-erox-page>元素中 列出的查询字符串是一个标志,用于告诉JSP显示这条消息)。 现在应该比较清楚了。不过,上面仅仅讲解登录过程,这当然是应用程序所需要的,但是怎样 限制DwR的远程访问类和方法呢?可以在awr.xm中找到答案,这也是接下来我们要讲述的内容 3. 到目前为止,已经多次讨论DWR配置文件了,因此你应该比较熟悉它了。代码清单5-5列出 这个配置文件。 代码清单5-5DWR配置文件dwr.xr
5.2 剖析 DWiki 92 加密。最后一种选择,可能也是最常用的,就是我们这里用的FORM。 FORM验证方法会导致容器重定向到某个登录页面,可以在<form-login-page>元素中配置这 个登录页面,在这个应用程序中配置的页面是login.jsp。当然,并没规则说要使用什么样的JSP 页面(事实上,甚至可以不使用JSP页面,可以是普通的HTML页面,或者如果正在使用Struts并 且配置适当,则可以是一个Structs动作)。 J2EE安全的替代机制 这里讨论的容器管理安全机制并不是唯一的选择。Acegi是另一种可行的选择,它是一个 流行的安全框架,提供了J2EE安全所没有的许多功能,也是可供大量用户访问的比较健壮的 基础架构。可以将Acegi集成到DWR中(虽然目前并没有正式开始支持这种集成)。DWR文档 给出了一个链接,指向一篇详细讲述Acegi与DWR集成的文章,如果有兴趣的话,可以看一下 (这里就不再进一步讨论这个主题了)。 由以上内容可知,事件的顺序是这样的,客户端请求受限资源,在本例中就是loginOk.jsp 文件。容器发现该资源被限制,便把客户端重定向到事先配置的登录页面login.jsp。后面将看 到,这个页面显示了一个特殊的表单以供用户输入自己的用户名和密码。这个表单会被提交给一 个特殊的servlet,该servlet使用tomcat-users.xml中的配置来验证这些信息。假设这些信息是 有效的,容器会返回客户请求的资源loginOk.jsp,用户便能有效登录。如果这些信息无效, 容器会将客户端重定向到<form-error-page>元素指定的页面,这个页面也是login.jsp,不 过这次页面中会以红色显示出一条消息,提示信息无效(请注意,<form-error-page>元素中 列出的查询字符串是一个标志,用于告诉JSP显示这条消息)。 现在应该比较清楚了。不过,上面仅仅讲解登录过程,这当然是应用程序所需要的,但是怎样 限制DWR的远程访问类和方法呢?可以在dwr.xml中找到答案,这也是接下来我们要讲述的内容。 3. dwr.xml 到目前为止,已经多次讨论DWR配置文件了,因此你应该比较熟悉它了。代码清单5-5列出 这个配置文件。 代码清单5-5 DWR配置文件dwr.xml
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki93 <?xml version=1. 0 oding=" UTF-8 < DOCTYPE dwr PUBLIC"-//GetAhead Limited//DTD Direct Web Remoting 2. 0//EN all <convert converter="bean"match="com. apress. dwrprojects wiki Article"/> <convert converter="bean tch="com. apress. dwrprojects wiki ArticleComment"/> <create creator="new"javascript="ArticleDA0"> param name="class"value="com. apress. dwrprojects wiki ArticleDA0"/> auth method="addArticle" role="dwiki user"/> <auth method="updateArticle role="wiki user"/> uth method="addComment role="wiki user"/> </allow> 有两个类 Artic1e和 Articlecomment需要在客户端和服务器之间传递,因此需要为它们指 转换器。这里,基本的bean转换器可以很好地完成这个任务 接着,指定 Artic1eDAo类可远程访问。实际上,它也是这个应用程序中唯一需要远程访问的 下面要讨论的是新内容。在这里,我们第一次遇到<auth>元素,不过它可不简单。对于每 个希望限制的方法,都要创建一个<auth>元素,其中指定需要限制的方法名以及允许执行它的 角色。没有列出的所有方法都可以被任何人访问。这样做正是我们所期望的,因为只有那三个方 法要求用户事先注册。 有了这样的设置,DWR会使用 request. isUserinrole()函数来确定指定的方法调用是否 被允许。一旦用户通过上面一节讲述的登录流程,它们会得到一个 cookie,用于将用户与容器中 记录用户角色的表对应起来,这个表正是 request, isUserinRo1e()返回的信息 我告诉过你,DWR可以大大简化这些操作。看吧,我没有开玩笑! 4. wiki,pr。 perties 最后一个配置文件是 wiki. properties,这是一个简单的Java属性文件,用于为 WIki应 用程序提供必要的信息(如代码清单5-6所示)。 代码清单5-6Dwik专用的配置文件 wiki. properties databaseDriver=org. apache derby. jdbc. EmbeddedDriver databaseURI=jdbc: derby: wiki; create=true databaseUsername databasepas= ditLockTime=60
5.2 剖析 DWiki 93 有两个类Article和ArticleComment需要在客户端和服务器之间传递,因此需要为它们指 定转换器。这里,基本的bean转换器可以很好地完成这个任务。 接着,指定ArticleDAO类可远程访问。实际上,它也是这个应用程序中唯一需要远程访问的 类。 下面要讨论的是新内容。在这里,我们第一次遇到<auth>元素,不过它可不简单。对于每 个希望限制的方法,都要创建一个<auth>元素,其中指定需要限制的方法名以及允许执行它的 角色。没有列出的所有方法都可以被任何人访问。这样做正是我们所期望的,因为只有那三个方 法要求用户事先注册。 有了这样的设置,DWR会使用request.isUserInRole()函数来确定指定的方法调用是否 被允许。一旦用户通过上面一节讲述的登录流程,它们会得到一个cookie,用于将用户与容器中 记录用户角色的表对应起来,这个表正是request.isUserInRole()返回的信息。 我告诉过你,DWR可以大大简化这些操作。看吧,我没有开玩笑! 4. dwiki.properties 最后一个配置文件是dwiki.properties,这是一个简单的Java属性文件,用于为DWiki应 用程序提供必要的信息(如代码清单5-6所示)。 代码清单5-6 DWiki专用的配置文件dwiki.properties