??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲午夜视频在线观看,亚洲欧洲无卡二区视頻,亚洲国产成人精品无码区二本http://www.tkk7.com/waterjava/category/31364.html我胡汉山又回来了!zh-cnThu, 08 May 2008 12:53:09 GMTThu, 08 May 2008 12:53:09 GMT60acegi,IBM的Acegi Security SystemQ?Q?http://www.tkk7.com/waterjava/archive/2008/05/08/199314.html狼爱上狸狼爱上狸Thu, 08 May 2008 10:50:00 GMThttp://www.tkk7.com/waterjava/archive/2008/05/08/199314.htmlhttp://www.tkk7.com/waterjava/comments/199314.htmlhttp://www.tkk7.com/waterjava/archive/2008/05/08/199314.html#Feedback0http://www.tkk7.com/waterjava/comments/commentRss/199314.htmlhttp://www.tkk7.com/waterjava/services/trackbacks/199314.html2008 q?3 ?20 ?/p>
Bilal Siddiqui l在他的 pd文章 中展C如何?Acegi 保护 Java™Server Faces (JSF) 应用E序。配|?JSF ?AcegiQ让它们?servlet 容器中协作,探烦 JSF ?Acegi lg如何彼此协作?/blockquote>

?pd 的前 3 部分讨论了如何?Acegi Security System 保护 Java 企业应用E序Q?/p>

  • W?1 部分 解释了如何?Acegi 的内|过滤器实现一个简单的Z URL 的安全系l?
  • W?2 部分 展示了如何编写访问控制策略、将其存储在 LDAP 目录服务器中Q以及配|?Acegi ?LDAP 服务器交互,从而实现访问控制策略?
  • W?3 部分 展示了如何在企业应用E序中?Acegi 保护?Java cd例的讉K?

W?4 部分讨论如何?Acegi 保护?servlet 容器中运行的 JavaServer Faces (JSF) 应用E序。本文首先解?Acegi 针对此目标提供的Ҏ,q澄清一些关于?Acegi ?JSF 的常见误解。然后提供一个简单的 web.xml 文gQ可以用来部|?AcegiQ从而保?JSF 应用E序。然后深入探?Acegi ?JSF lgQ了解在部v web.xml 文g和用戯?JSF 应用E序时所发生的事件。本文最后提供了一个由 Acegi 保护的示?JSF 应用E序?

无需~写 Java 代码卛_d安全?/span>

回顾一下本pd的第一个示?Acegi 应用E序Q请参阅 W?1 部分 中的 “一个简?Acegi 应用E序” 一节)。该应用E序使用 Acegi 提供了以下安全特性:

  • 当一个未l验证的用户试图讉K受保护的资源Ӟ提供一个登录页面?
  • 授权用L接重定向到所需的受保护资源?
  • 如果用户未被授权讉K受保护资源,提供一个访问拒l页面?

回想一下,您无需~写M Java 代码p获得q些Ҏ。只需要对 Acegi q行配置。同P?JSF 应用E序中,无需~写M Java 代码Q也应该能够?Acegi 实现相同的特性?/p>

澄清误解

其他一些作者似乎认为将 Acegi ?JSF 集成需?JSF 应用E序提供d面Q参?参考资?/a>Q。这U观点ƈ不正。在需要时提供d面Q这?Acegi 的职责。确保登录页面在安全会话期间只出Cơ,q也?Acegi 的职责。然后,l过w䆾验证和授权的用户可以讉K一个受保护资源Q无需重复执行dq程?/p>

如果使用 JSF 提供d面Q将会发生两个主要的问题Q?/p>

Acegi 的目的是避免~写 Java 安全代码。如果?JSF 提供d面Q则没有实现q一用途,q且会引发一pd其他 JSF-Acegi 集成问题Q所有这些问题都源于 “Acegi 是用来提供可配置安全?#8221; q一事实。如果试图?JSF 来完?Acegi 的工作,会遇到ȝ?/p>

本文余下部分解释ƈ演示独立?Acegi ?JSF 应用E序开发,q在E后配置 Acegi 以保?JSF 应用E序 ?无需~写M Java 代码。首先看一?web.xml 文gQ可以部|该文g保护 JSF 应用E序?/p>



回页?/strong>


部v Acegi 保护 JSF 应用E序

清单 1 展示了一?web.xml 文gQ通常UCؓ部v描述W?/em>Q,可以使用q个文g部v AcegiQ从而保护运行在 servlet 容器Q比?Apache TomcatQ中?JSF 应用E序Q?/p>
清单 1. 用于部v Acegi ?servlet 容器中的 JSF ?web.xml 文g
                        <?xml version="1.0"?>
            <!DOCTYPE web-app PUBLIC
            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
            "http://java.sun.com/dtd/web-app_2_3.dtd">
            <web-app>
            <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/acegi-config.xml</param-value>
            </context-param>
            <context-param>
            <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
            <param-value>server</param-value>
            </context-param>
            <context-param>
            <param-name>javax.faces.CONFIG_FILES</param-name>
            <param-value>/WEB-INF/faces-config.xml</param-value>
            </context-param>
            <listener>
            <listener-class>
            org.springframework.web.context.ContextLoaderListener
            </listener-class>
            </listener>
            <listener>
            <listener-class>
            com.sun.faces.config.ConfigureListener
            </listener-class>
            </listener>
            <!-- Faces Servlet -->
            <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup> 1 </load-on-startup>
            </servlet>
            <!-- Faces Servlet Mapping -->
            <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.faces</url-pattern>
            </servlet-mapping>
            <!-- Acegi filter configuration -->
            <filter>
            <filter-name>Acegi Filter Chain Proxy</filter-name>
            <filter-class>
            org.acegisecurity.util.FilterToBeanProxy
            </filter-class>
            <init-param>
            <param-name>targetClass</param-name>
            <param-value>
            org.acegisecurity.util.FilterChainProxy
            </param-value>
            </init-param>
            </filter>
            <!-- Acegi Filter Mapping -->
            <filter-mapping>
            <filter-name>Acegi Filter Chain Proxy</filter-name>
            <url-pattern>/*</url-pattern>
            </filter-mapping>
            </web-app>
            

注意Q?a cmimpressionsent="1">清单 1 包含以下标记Q?/p>

  • 3 ?<context-param> 标记
  • 2 ?<listener> 标记
  • 1 ?<filter> 标记
  • 1 ?<servlet> 标记
  • 1 ?<servlet-mapping> 标记
  • 1 ?<filter-mapping> 标记

阅读该文Ӟ了解每个标记?JSF-Acegi 应用E序中的用途?/p>

?Acegi ?JSF 提供上下文参?/span>

清单 1 中的每个 <context-param> 标记定义一个参敎ͼ?Acegi ?JSF 在启动或执行期间使用。第一个参??contextConfigLocation ?定义 Acegi ?XML 配置文g的位|?/p>

JSF 需?javax.faces.STATE_SAVING_METHOD ?javax.faces.CONFIG_FILES 参数?code>javax.faces.STATE_SAVING_METHOD 参数指定希望在客hq是服务器上存储 JSF 面-视图状态。Sun 的参考实现的默认行ؓ是将 JSF 视图存储在服务器上?/p>

javax.faces.CONFIG_FILES 参数指定 JSF 需要的配置文g的位|。JSF 配置文g的详l信息不属于本文讨论的范_参见 参考资?/a>Q获取涉及该主题的资源链接)?/p>

?Acegi ?JSF 配置侦听?/span>

现在看一?清单 1 中的 2 ?<listener> 标记?code><listener> 标记定义侦听器类Q侦听器cM听ƈ处理 JSP ?servlet 应用E序启动和执行期间发生的事g。例如:

  • 启动 JSP ?servlet 应用E序Ӟservlet 容器创徏一个新?servlet 上下文。每?JSP ?servlet 应用E序启动Ӟ׃触发此事件?br />
  • servlet 容器创徏一个新?servlet h对象。每当容器从客户机收C?HTTP hӞ此事件就会发生?

  • 建立一个新?HTTP 会话。当h客户机徏立一个与 servlet 容器的会话时Q此事g׃发生?

  • 一个新属性被d?servlet 上下文、servlet h?HTTP 会话对象?br />
  • servlet 上下文、servlet h?HTTP 会话对象的一个现有属性被修改或删除?

<listener> 标记像一U可扩展性机Ӟ允许?servlet 容器内部q行的应用程序协同某些事件进行处理。servlet 规范定义了侦听器cMؓ处理事g而实现的一些接口?/p>

例如QSpring Framework 实现一?javax.servlet.ServletContextListener servlet 接口。实现此接口?spring cL org.springframework.web.context.ContextLoaderListener。注意,q是 清单 1 的第一?<listener> 标记中的侦听器类?

cM圎ͼJSF 实现一?com.sun.faces.config.ConfigureListener c,该类实现一些事?侦听接口。可以在 清单 1 的第二个 <listener> 标记中找?ConfigureListener cR?/p>

本文E后解释不同的事g-侦听器接口,以及 Acegi ?JSF 事g-侦听器类内部执行的处理(请参?“启动 JSF-Acegi 应用E序” ?“处理对受 Acegi 保护?JSF 面的请?/a>”Q?/p>

配置和映?servlet qo?/span>

现在看一?清单 1 中的 <filter> 标记。在h?servlet 处理传入的请求之前,servlet 应用E序使用qo器对其进行预处理。在h执行之前QAcegi 使用 servlet qo器对用户q行w䆾验证?/p>

h?清单 1 中的 <filter> 标记Q它?<filter-class> 子标记指定一?org.acegisecurity.util.FilterToBeanProxy cR?code>FilterToBeanProxy cL Acegi 的一部分。此cdC?javax.servlet.Filter 接口Q该接口?servlet 应用E序的一部分?code>javax.servlet.Filter 接口有一?doFilter() ҎQservlet 容器在收到请求时调用该方法?/p>

q需注意Q?a cmimpressionsent="1">清单 1 ?<filter> 标记有另一个子标记 <init-param>?code><init-param> 标记指定实例?FilterToBeanProxy cL需的参数。可以从 清单 1 中看出,FilterToBeanProxy cd需要一个参敎ͼ该参数是 FilterChainProxy cȝ一个对象?code>FilterChainProxy c表C?W?1 部分 1 中讨论的整个 Acegi qo器链Q请参阅 “安全qo?#8221; 节Q?code>FilterToBeanProxy cȝ doFilter() Ҏ使用 FilterChainProxy cL?Acegi 的安全过滤器链?/p>

清单 1 中的 <filter-mapping> 标记指定调用 Acegi ?FilterToBeanProxy 的请?URL。我已经所有的 JSF 面映射?Acegi ?FilterToBeanProxy。这意味着只要用户试图讉K JSF 面Q?code>FilterChainProxy doFilter() Ҏ׃自动获得控制权?/p>

配置 JSF servlet

web.xml 文g中的 <servlet> 标记指定希望从特?URl 调用?servletQ在本例中是一?JSF servletQ?code><servlet-mapping> 标记定义?URL。几乎所有的 JSP ?servlet 应用E序都包含这两个标记Q所以无需再作讨论Q参?参考资?/a>Q获取讨?servlet ~程的资源链接)?/p>

现在Q您已经看到Qweb.xml 文g要部|?Acegi 以保?JSF 应用E序所需的所有标记。您已经了解了侦听器、过滤器?servlet 如何怺协作。从q里的讨Z可以看出Q如果在 servlet 容器中部|?清单 1 中的 web.xml 文gQAcegi ?JSF 都试囑֜两种情Ş下进行一些处理:

  • 当启动应用程序时
  • 当应用程序收到对 JSF 面的请求时

接下来的两节解释每种情况中发生的一pd事g?





回页?/strong>


启动 JSF-Acegi 应用E序

?1 展示了在 JSF-Acegi 应用E序启动时发生的事g序Q?/p>
?1. JSF-Acegi 应用E序启动时发生的事g序
JSF-Acegi 应用E序启动时发生的事g序


详细来讲Q?a cmimpressionsent="1">?1 昄的事仉序如下所C:

  1. servlet 容器实例化在 web.xml 文g中配|的所有侦听器?br />
  2. servlet 容器?Acegi ?ContextLoaderListener 注册Z个侦听器c,该类实现 javax.servlet.ServletContextListener接口?code>ServletContextListener 接口包含两个重要ҎQ?code>contextInitialized() ?contextDestroyed()Q?
    • contextInitialized() Ҏ在初始化 servlet 上下文时获得控制权?
    • cM圎ͼ当应用程序退出时Q?code>contextDestroyed() Ҏ会被调用Qƈ消除 servlet 上下文?

  3. servlet 容器?JSF ?ConfigureListener 注册为另一个侦听器。JSF ?ConfigureListener 实现许多侦听器接口,比如 ServletContextListener?ServletContextAttributeListener?ServletRequestListenerQ以?ServletRequestAttributeListener。您已经看到?ServletContextListener 接口的方法。余下的接口是:
  4. servlet 容器创徏一?servlet 上下文对?/em>Q该对象装应用E序资源Q比?JSP 面、Java cd应用E序初始化参敎ͼQƈ允许整个应用E序讉Kq些资源。JSF-Acegi 应用E序的所有其他组Ӟ侦听器、过滤器Q以?servletQ在 servlet 上下文对象中以属性的形式存储与应用程序资源相关的信息?br />
  5. servlet 容器通知 Acegi ?ContextLoaderListenerQservlet 上下文是通过调用 ContextLoaderListener ?contextInitializated() Ҏ初始化的?br />
  6. contextInitialized() Ҏ解析 Acegi 的配|文Ӟ?JSF-Acegi 应用E序创徏 Web 应用E序上下文,以及实例化所有的安全qo器和?Acegi 配置文g中配|的 Jave bean。在以后 JSF 应用E序收到来自客户机的hӞq些qo器对象将会用于n份验证和授权Q参?W?3 部分 中关?Web 应用E序上下文创建的讨论和图 1Q?

  7. servlet 容器通知 JSF ?ConfigureListenerQservlet 上下文是通过调用 contextInitialized() Ҏ初始化的?br />
  8. contextInitialized() Ҏ查在 JSF 配置文g中配|的所?JSF 托管 beanQ确?Java cM每个 bean q存?br />
  9. servlet 容器?web.xml 文g中Q何配|的qo器。例如,清单 1 中的 web.xml 文g包含一?Acegi qo?FilterToBeanProxyQservlet 容器其实例化、初始化q注册ؓ一个过滤器。Acegi 现在可以对传入的h执行w䆾验证和授权了?

  10. servlet 容器实例?faces servletQ后者开始侦听从用户传入的请求?

下一节解?JSF-Acegi 应用E序收到来自用户的请求时发生的一pd事g?/p>



回页?/strong>


处理对受 Acegi 保护?JSF 面的请?/span>

您已l了解了如何配置 Acegi 保护 JSF 应用E序。也看到了当启动 JSF-Acegi 应用E序时发生的一pd事g。本节描q当用户发送一个对?Acegi 保护?JSF 面的请求时QJSF ?Acegi lg如何?servlet 容器的框架中q行?/p>

?2 展示了当客户机发送一个对?Acegi 保护?JSF 面的请求时Q发生的事g序Q?/p>
?2. JSF ?Acegi 协作提供 JSF 面
JSF ?Acegi 协作提供 JSF 面


详细来讲Q?a cmimpressionsent="1">?2 展示的事仉序如下所C:

  1. servlet 容器创徏一个表C用戯求的 servlet h对象?br />
  2. 回想一?启动 JSF-Acegi 应用E序 节中的W?3 步,JSF ?ConfigureListener 实现 ServletRequestListener 接口。这意味着 ConfigureListener 侦听与创建和删除 servlet h对象相关的事件。因此,servlet 容器调用 ConfigureListenerrequestInitialized() Ҏ?br />
  3. requestInitialized() Ҏ准备执行h?JSF 生命周期。准备过E包括检查请求的 faces 上下文是否存在。faces 上下文封装与应用E序资源相关的信息。faces servlet 执行 JSF 生命周期旉要这些信息。如果此h是新会话的第一个请求,׃~少 faces 上下文。在q种情况下,requestInitialized() Ҏ创徏一个新?faces 上下文?br />
  4. servlet 容器查用Lh是否带有M状态信息。如?servlet 容器未找到状态信息,它会假设该请求是C话的W一个请求,qؓ用户创徏一?HTTP 会话对象。如?servlet 容器发现该请求包含某U状态信息(比如一?cookie ?URL 中的某种状态信息)Q它׃Ҏ保存的会话信息恢复用户以前的会话?br />
  5. servlet 容器把请?URL 与一?URL 模式q行匚wQ这?URL 模式包含在配|描q符中的 <filter-mapping> 标记?<url-pattern> 子标C。如果请?URL 与这?URL 模式匚wQservlet 容器调用 Acegi ?FilterToBeanProxyQ?code>FilterToBeanProxy 已在 ?1 的第 9 步中被注册ؓ一?servlet qo器?br />
  6. Acegi ?FilterToBeanProxy 使用 FilterChainProxy cL?Acegi 的完整的安全qo器链。Acegi 的过滤器自动查第 4 步中创徏?HTTP 会话对象Q以查看h客户机是否已被验证。如?Acegi 发现用户未被验证Q它提供一个登录页面。否则,它就直接执行 W?2 部分 ?“配置拦截?#8221; 一节中描述的授权过E?

  7. Acegi 使用l过验证的用L会话信息更新 servlet 上下文?br />
  8. servlet 容器通知 JSF ?ConfigureListener ?attributeReplaced() ҎQservlet 上下文已被更新?code>ConfigureListener 查是否有M JSF bean 被更攏V如果发CQ何更改,它相应地更新 faces 上下文。但是,在本例中Q在w䆾验证q程?Acegi 没有更改M JSF 托管 beanQ因此在此调用期?ConfigureListener 不进行Q何处理?br />
  9. 如果授权q程成功Q控制权被{Ud faces servletQ它执行 JSF 生命周期q向用户发回一个响应?

现在Q您了解?JSF ?Acegi 如何协作提供 JSF hQ接下来看一下完成后?JSF ?Acegi?/p>



回页?/strong>


CZ JSF-Acegi 应用E序

本文的下载部分(参见 下蝲Q包含一个示?JSF-Acegi 应用E序 JSFAcegiSampleQ演CZ Acegi ?JSF 的简单集成。示例应用程序?清单 1 中的 web.xml?

要部|示例应用程序,执行 W?1 部分 ?“部vq运行应用程?#8221; 一节中的两个步骤。还需要从 Sun ?JSF 站点Q参?参考资?/a>Q下载ƈ解压 jsf-1_1_01.zip。将 jsf-1.1.X.zip 中的所有文件复制到 JSFAcegiSample 应用E序?WEB-INF/lib 文g夹中?/p>

从浏览器讉K http://localhost:8080/JSFAcegiSampleQ可以调用示例应用程序。JSFAcegiSample 应用E序昄一个烦引页面和一个登录页面,索引面中包含受保护资源的链接。所有受保护面都是使用 JSF lg开发的Q?Acegi 提供d面q执行n份验证和授权?/p>



l束?/span>

在本文中Q了解了如何配置 Acegi 以保?JSF 应用E序。还详细了解?JSF ?Acegi lg如何在一?servlet 容器的框架中协作。最后,试q行了一个示?JSF-Acegi 应用E序?/p>

关于实现 JSF 应用E序?Acegi 安全性,q涉及到更多内容。本pd的下一文章将演示如何使用 Acegi 保护?JSF 的托?bean 的访问?br />

来自: http://www.cnblogs.com/amboyna/archive/2008/03/25/1122089.html



狼爱上狸 2008-05-08 18:50 发表评论
]]>acegi,IBM的Acegi Security SystemQ?Q?http://www.tkk7.com/waterjava/archive/2008/05/08/199312.html狼爱上狸狼爱上狸Thu, 08 May 2008 10:47:00 GMThttp://www.tkk7.com/waterjava/archive/2008/05/08/199312.htmlhttp://www.tkk7.com/waterjava/comments/199312.htmlhttp://www.tkk7.com/waterjava/archive/2008/05/08/199312.html#Feedback0http://www.tkk7.com/waterjava/comments/commentRss/199312.htmlhttp://www.tkk7.com/waterjava/services/trackbacks/199312.html2007 q?10 ?18 ?/p>
本文?Acegi Security Systerm 介绍的最后一部分Q共三部分)QBilal Siddiqui 向您介l如何保护对 Java cd例的讉KQ从而结束本pd文章。通过本文了解Z需要对 Java™ cȝ讉Kq行保护QSpring 如何创徏和保护对 Java cd例的讉K以及如何?Acegi q行配置以实?Java 应用E序的类安全性?/blockquote>

q期共分三部分的pd文章介绍了如何?Acegi 安全pȝ保护 Java 企业应用E序。系列文章的 W?1 部分 单介l了 Acegi q解释如何用其内置的安全过滤器实现一个简单的、基?URL 的安全系l?a cmimpressionsent="1">W?2 部分 介绍了如何编写访问控制策略ƈ其保存C?LDAP 目录服务器,以及如何配置 Acegi 来与目录服务器进行交互,从而实现访问控制策略。第 3 部分Q也是本pd的最后一文章)演C如何在企业应用E序中?Acegi 保护?Java cd例的讉K?

首先我将介绍何时需要对 Java c访问进行保护,包括文中引用的两个典型企业应用程序场景。之后,我将解释 Spring 的反转控ӞIOCQ框架如何创建可?JSP ?servlet 讉K?Java cd例。我q将介绍有关 bean 代理 的重要概念,Spring 正是使用它过滤对 Java cȝ讉K。最后,我将介绍如何?Acegi 的方法安全性拦截器q行配置以控制对 Java cȝ讉K。我对 W?2 部分 中的CZE序q行增强Qؓ实现安全?Java 对象提供支持Q从而结束本pd的最后一文章?

׃本文的讨论构建在本系列前两部分的内容之上Q因此会l常引用?W?1 部分 ?W?2 部分 中的讨论和示例。因此,在l阅L文之前,在其他浏览器H口中打开前两期文章将有助于理解本文内宏V?/p>

保护 Java cȝ用例

您可能还记得Q我曑֜本系列的开头部分简单介l了 企业应用E序安全?/a>。在那次讨论中我曾提到过一U场景,其中 URL 安全性ƈ不能完全满q种场景的安全需求:

假设有这样一?PDF 文Q其中包含了某制造业公司生的特定品的数据。文档的一部分包含了设计数据,由公司设计部分q行~辑和更新。文另一部分包含生l理用到的生产数据。对于此cd景,需要实现更加细_度的安全性,Ҏ档的不同部分应用不同的访问权限?/blockquote>

在l阅M前,误虑更多的应用程序场景,除了实现 URL 安全性以外,q些场景q要求您对单独的c访问进行保护?/p>

业务自动?/span>

业务自动化应用程序中的工作流由多个流E组成。例如,病理学实验室中执行血液测试的工作由若干个步骤组成,其中每个步骤可看作一个业务流E:

  1. 工作人员从病人处采集血液样本ƈ为其分配一?ID?
  2. 实验室技术h员对hq行必要的测试ƈ准备试l果?
  3. 由具备相应资格的病理学专家根据测试结果编写测试报告?

很明显,每个程分别由单独的授权用户执行。未授权的用户则无权执行程。例如,实验室研Ih员只负责准备试验l果Q而无权编写测试报告?/p>

几乎所有的业务自动化应用程序都普遍使用授权的业务流E。通常Q每个业务流E被实现Z?Java c,q且需要用合适的讉K控制{略Ҏ有类实施保护?/p>

企业对企业(Business-to-businessQ集?/span>

Business-to-business (B2B) 集成指一U常见的场景Q其中的两个企业实体需要彼此公开各自的特定功能。例如,N可能向旅游公司公开其房间预订功能,而后者用该功能为游客预订空闲的戉K。作为合作伙伴的旅游公司可能h一个特定的订房率。在q个场景中,N的订房系l必dҎ游公司进行n份验证,然后才能允许他们讉K所选择的类Q以便按照特定的订房率进行房间预订?/p>



回页?/strong>


使用 Spring 创徏 Java 对象

现在您已l了解了?Java cȝ例的讉Kq行保护的重要性。在介绍能够实现更高U安全性的 Acegi 新功能之前,我将引导您回?Spring 框架的几个关键特性,您需要了解这些内Ҏ能l后文的CZ?/p>

首先对一?Java c进行配|ƈ执行实例化?a cmimpressionsent="1">W?1 部分 曾介l过QJava cd Spring ?XML 配置文g中进行配|。在 Spring 配置文g中配|?Java cȝq程?Acegi qo器的配置q程完全相同Q因此这里不多做介绍。相反,我们查看清?1Q它展示了名?publicCatalog ?bean 的配|:


清单 1. Acegi XML 配置文g
            <beans>
            <bean id="publicCatalog"
            class="com.catalog.PublicCatalog" />
            <!--Other bean tags -->
            <beans>
            

了解 Spring ?IOC 框架如何?XML 配置文gd Java cM息以及如何进行实例化Q这一炚w帔R要。您可能q记得,我在pd文章?W?1 部分 中用一?web.xml 文g配置 <listener> 标记Q它指向名ؓ ContextLoaderListener 的类?code>ContextLoaderListener 装蝲 Spring ?IOC 框架q创?Java 对象。您可以参?W?1 部分的清?8 查看全部内容。图 1 也对此进行了描述Q?/p>
?1. 装蝲 Spring ?IOC 框架q创?Java 对象
装蝲 Spring ?IOC 框架q创?Java 对象的步? src=

现在我们详l讨些步骤:

  1. 当初始化 Acegi 应用E序Ӟservlet 容器Q本例中?Apache TomcatQ创Z一?servlet 上下?/em>Q其中保存了有关应用E序资源的信息,例如 JSP 面和类?br />
  2. servlet 容器通知 ContextLoaderListener cd用程序正在启动?br />
  3. ContextLoaderListener cdZ?Web 应用E序上下文以保存应用E序中特定于 Spring 的资源信息。借助 Spring ?IOC 框架Q您可以装蝲自己的自定义应用E序上下文。要创徏应用E序上下文,用名?ContextLoader 的上下文装蝲器类装蝲应用E序上下文?br />
  4. 如果应用E序不需要定义自q应用E序上下文,则可以用名?XMLWebApplicationContext 的类Q它?Spring 框架的一部分q提供可处理 Spring XML 配置文g的功能。Acegi 应用E序使用的是 Spring ?XML 配置文gQ因此本文仅讨论?XMLWebApplicationContext c表C的应用E序上下文。在本例中,上下文装载器?XMLWebApplicationContext c进行实例化Q后者表C您?Acegi 应用E序的应用程序上下文。上下文装蝲器还?Web 应用E序上下文中讄 servlet 上下文(于步?1 中创建)的引用?br />
  5. XMLWebApplicationContext cd XML 配置文gq行解析Q获得关?Java cȝ信息q将信息装蝲到其他内部对象中?br />
  6. XMLWebApplicationContext cd XML 配置文g中指定的所?Java c进行实例化?code>XMLWebApplicationContext cL?XML 配置文g中经q配|的 Java bean 是否依赖其他?Java 对象。如果是的话Q?code>XMLWebApplicationContext cd首先对其?bean 所依赖?bean q行实例化。通过q种方式Q?code>XMLWebApplicationContext cdZ XML 配置文g中定义的所?bean 的实例。(注意Q步?6 假定 XML 配置文g中所?bean 都不要进行保护,E后一节将介绍步骤 5 和步?6 之间执行的额外步骤,从而保护对此处创徏?Java bean 的访问)?br />
  7. XMLWebApplicationContext cd所?bean 保存在一个数l中?

您现在已了解到如何从 XML 配置文g中装?bean 定义q创?Java cȝ实例。接下来Q我向您介l?Spring bean 代理q解释它对于保护 Java cd例的重要性?/p>



回页?/strong>


使用 bean 代理

上一节讨Z Spring ?IOC 框架?Java 对象q行实例化。要保护?Java 对象的访问,Spring ?IOC 框架使用?bean 代理 的概c本节首先介l如何配|?bean 代理Q然后演C?Spring ?IOC 框架如何创徏代理对象?/p>

?Java 对象配置代理

如果希望创徏 bean 代理QSpring IOC 框架要求您对代理创徏?bean 的实例进行配|。Spring ?IOC 框架使用代理创徏器创Z理对象。清?2 Z理创建器 bean 的配|文Ӟ用于保护名ؓ privateCatalog ?Java 对象Q?/p>
清单 2. 代理 bean 配置
            <bean id="proxyCreator"
            class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="beanNames">
            <list>
            <value>privateCatalog</value>
            <!--Names of other beans to be proxied -->
            </list>
            </property>
            <property name="interceptorNames">
            <list>
            <value>privateCatalogSecurityInterceptor</value>
            </list>
            </property>
            </bean>
            

如清?2 所C,<bean> 标记h一?class 属性,其gؓ org.springframework.aop.framework.autoproxy. BeanNameAutoProxyCreator?code>BeanNameAutoProxyCreator cL Spring IOC 框架的一部分Q可以自动创?bean 代理。Spring 框架提供?BeanPostProcessor 接口Q它提供了一U可扩展机制Q允许应用程序编写自q逻辑来创?bean 代理。Spring ?BeanNameAutoProxyCreator cdC BeanPostProcessor 接口q提供所有必需的代理创建逻辑来保?Java cR因此,本文中您无需实现 BeanPostProcessor 接口?/p>

在创?bean 代理ӞBeanNameAutoProxyCreator cMؓ所有由 beanNames 属性定义的 bean 创徏代理Q参?清单 2 ?<bean> 标记的第一?<property> 子元素)?code>beanNames 属性在 <list> 标记中包含一?bean 名称列表。在 清单 2 中,我只对希望ؓ之创Z理的 privateCatalog beanq行了配|?/p>

现在查看 清单 2 ?<bean> 标记的第二个 <property> 子元素。它指定了名?interceptorNames 的代理,它将一个或多个拦截器的名称装h。我在后文详细讨论拦截器概c现在,只需了解拦截器可以拦截用户ƈ在用戯?bean 之前实现讉K控制{略?/p>

现在Q您已了解了如何对希望进行保护的 bean 配置代理。接下来Q您了?Spring ?IOC 框架如何在内部ؓ应用E序?bean 创徏代理对象?/p>

Spring IOC 发挥效用

?“使用 Spring 创徏 Java 对象” 的步?5 和步?6 中,您了解了 XMLWebApplicationContext cd何从 XML 配置文g中读?bean 定义q后创?bean 实例。在创徏 bean 实例之前Q?code>XMLWebApplicationContext cd?XML 配置文g是否包含M代理创徏?beanQ即实现 BeanPostProcessor 接口?beanQ配|。如果存在该 beanQ它要求代理创建器为您希望q行保护?bean 创徏 bean 代理?/p>

现在考虑代理创徏器如何在内部创徏代理对象Q?/p>

  1. 代理创徏器(?BeanNameAutoProxyCreator c)装蝲 清单 2 中配|的 beanNames 属性文件中指定的所?bean 名称?br />
  2. 代理创徏器?bean 名称装蝲各自?Java c,q些cM用了每个 bean 定义?class 属性?br />
  3. 代理创徏器创?清单 2 所C的 interceptorNames 属性中指定的拦截器的实例?br />
  4. 最后,代理创徏器创Z?Cglib2AopProxy cȝ实例Q将所?bean 名称Q步?2Q和拦截器(步骤 3Q传递到 Cglib2AopProxy cR?code>Cglib2AopProxy cL Spring 框架的一部分q用于生成动态代理对象。在本例中,Cglib2AopProxy cd创徏安全 bean 讉K控制所需的代理对象?

Cglib2AopProxy cdC两个名ؓ AOPProxy ?MethodInterceptor 的接口?code>AOPProxy 接口?Spring 框架提供Q表C您希望q行代理的实?beanQ因此它与您?bean 公开相同的方法?code>MethodInterceptor 接口也源?AOP 框架Q它包含的方法可以在用户试图讉K您已执行代理?bean 时接受控制权。这意味着 MethodInterceptor 接口处理来自用户的请求以讉K执行q代理的 bean。由?Cglib2AopProxy cd时实C AOPProxy ?MethodInterceptor 接口Q因此它提供了完整的功能Q既可以提供l过代理?beanQ也可以处理用户h以访问代?beanQ参?参考资料小?/a> 中有?AOP 的讨论文章的链接Q?/p>

执行完前面的步骤后,您现在具有了所需的代理对象。因?XMLWebApplicationContext cd安全 bean 的代理(而不是实际的 beanQ保存在 “使用 Spring 创徏 Java 对象” 的步?7 中的同一个数l中?





回页?/strong>


讉K执行q代理的 Java 对象

在前面的几节中,您了解了 Spring 如何创徏公有 bean 和私?bean。出于本文的目的Q您可将公有 bean 视ؓ使用代理保护的不安全的私?bean。现在我们来看一下客h应用E序问公?bean 和私?bean 而必遵循的一pd步骤?/p>

清单 3 展示?publicCatalog ?privateCatalog 两个 bean ?XML 配置?code>publicCatalog bean 意味着公共讉KQ因此不需要?bean 代理?code>privateCatalog bean 意味着只能由指定用戯问,因此必须加以保护。我在清?3 中包含了 privateCatalog bean ?bean 代理配置Q?/p>
清单 3. publicCatalog ?privateCatalog bean ?XML 配置
            <beans>
            <bean id="publicCatalog" class="sample.PublicCatalog"/>
            <bean id="privateCatalog" class="sample.PrivateCatalog"/>
            <!-- proxy configuration for privateCatalog bean -->
            <bean id="proxyCreator"
            class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="beanNames">
            <list>
            <value>privateCatalog</value>
            <!--Names of other beans to be proxied -->
            </list>
            </property>
            <property name="interceptorNames">
            <list>
            <value>privateCatalogSecurityInterceptor</value>
            </list>
            </property>
            </bean>
            <beans>
            

应用E序可以使用清单 4 中的代码讉K清单 3 中配|的 publicCatalog ?privateCatalog Java bean。注意,清单 4 中显C的 Java 代码可位?JSP 面或位于服务器?Java 应用E序?bean 中?/p>
清单 4. 讉K安全和不安全 Java bean 的客h应用E序代码
            //Step 1: Fetching an instance of the application context
            XMLWebApplicationContext applicationCtx =
            WebApplicationContextUtils.getWebApplicationContext(
            this.getServletConfig().getServletContext());
            //Step 2: Fetching an insecure bean from the application context
            PublicCatalog publicCatalog =
            (PublicCatalog) applicationCtx.getBean("publicCatalog");
            //Step 3: Calling a method of the insecure bean
            String publicData = publicCatalog.getData();
            //Step 4: Fetching a secure bean from the application context
            PrivateCatalog privateCatalog =
            (PrivateCatalog) applicationCtx.getBean("privateCatalog");
            //Step 5: Calling a method of the secure bean
            String privateData = privateCatalog.getData();
            

下面进一步讨论清?4 中的步骤Q?/p>

  • 步骤 1Q取回一个应用程序上下文实例
    当应用程序希望访?XML 配置文g中配|的 Java bean Ӟ它必d回您?“使用 Spring 创徏 Java 对象” 的步?4 中见到的 XMLWebApplicationContext 对象?code>XMLWebApplicationContext 对象包含?XML 配置文g配置的所?Java beans 的引用?br />
  • 步骤 2Q从应用E序上下文中取回不安全的 bean
    您现在具有一个对 XMLWebApplicationContext 对象的引用?code>XMLWebApplicationContext cd开了一?getBean() ҎQ它包含 bean 的名Uƈ在数l中查找 “使用 Spring 创徏 Java 对象” 步骤 7 中准备的 bean。在本例中,?bean ?publicCatalogQ未执行q代理)Q因?XMLWebApplicationContext 返回实际的 bean?br />
  • 步骤 3Q调用不安全 bean 的方?/strong>
    现在您可以调用步?2 中获得的 publicCatalog bean 的Q何方法。例如,清单 4 昄?getData() Ҏ调用的执行没有应用Q何访问控制ƈ向应用程序返回类别数据?br />
  • 步骤 4Q从应用E序上下文取回安?bean
    安全 bean 与不安全 bean 的取回方式类|惟一区别是:当您通过调用 getBean() Ҏ试取回安全 bean Ӟ您将获得安全对象的代理而不是实际的对象。该代理是我在 “Spring IOC 发挥效用” 步骤 4 中解释的?Spring 框架创徏的同一个对象?br />
  • 步骤 5Q调用安?bean 的方?/strong>
    当调用安?bean 的方法时Q您?步骤 4 中获得的代理对象一个方法调用请求分配给拦截器。拦截器检查试图访问方法的用户是否h相应的访问权Q从而处理方法调用请求?

您现在应该对 Spring 框架如何创徏 Java 对象以及客户机应用程序如何与之交互有了清晰的了解。了解了q些内容后,更加容易理解ƈ利用 Acegi 的方法安全性拦截器Q下一节将具体介绍该主题?/p>



回页?/strong>


配置 Acegi 的方法安全性拦截器

只要应用E序试图讉K?Acegi 安全pȝ保护?bean ҎQ请求将被自动传递到 Acegi 的方法安全性拦截器。方法安全性拦截器的作用就是控制对安全 Java bean 的方法的讉K。拦截器使用 Acegi 的n份验证和授权框架认用户是否h权利调用安全 Java bean 的方法,然后相应C出响应?/p>

清单 5 展示 Acegi 的方法安全性拦截器的示例配|:


清单 5. Acegi 的方法安全性拦截器的示例配|?/strong>
            <bean id="privateCatalogSecurityInterceptor"
            class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
            <property name="authenticationManager">
            <ref bean="authenticationManager"/>
            </property>
            <property name="accessDecisionManager">
            <ref bean="accessDecisionManager"/>
            </property>
            <property name="objectDefinitionSource">
            <value>
            sample.PrivateCatalog.getData=ROLE_HEAD_OF_ENGINEERING
            <!-- Roles required by other beans -->
            </value>
            </property>
            </bean>
            

清单 5 所C的拦截器配|包含三个需要进行配|的属性,可以保护?Java bean 的访问:authenticationManager?code>accessDecisionManager ?objectDefinitionSource?/p>

回忆一下,您在本系列第 1 部分?配置w䆾验证处理qo?/a> 中曾?authenticationManager 属性进行了配置?code>authenticationManager 属性的作用是对用户q行w䆾验证?/p>

您在本系列的W二文章中了解?accessDecisionManager 属性。这个访问决{管理器负责制定授权决策。在允许对一个安?bean q行讉K之前Q方法安全拦截器使用 authenticationManager ?accessDecisionManager 属性对用户q行w䆾验证和授权?/p>

现在查看 清单 5 中配|的 objectDefinitionSource 属性。它cM于第 1 部分中出现的 objectDefinitionSource 属性。以前的 objectDefinitionSource 包含cM?/protected/* ?/** q样?URLQ清?5 中的 objectDefinitionSource 属性指定类和方法名Q例如,sample.PrivateCatalog 是之前执行过代理的类的名Uͼ?getData 是您希望对其控制用户讉K的方法的名字?/p>

当用戯?PrivateCatalog bean ?getData() ҎӞ控制权将自动传递给拦截器。拦截器使用 Acegi 框架查用L业务角色是否?ROLE_HEAD_OF_ENGINEERINGQ特定于本文的示例)。如果是的话Q拦截器允许对 getData() Ҏq行讉K。如果拦截器发现用户角色不是 ROLE_HEAD_OF_ENGINEERINGQ则拒绝讉K?/p>

下一节将查看一个示?Acegi 应用E序Q它实现您目前所了解的所有概c?/p>



回页?/strong>


CZ Acegi 应用E序

本文?下蝲源代?/a> 包含了一个名?AcegiMethodSecurity 的示例应用程序,可按照以下方法进行配|和部vQ?/p>

  1. 使用用户信息填充 LDAP 服务器?a cmimpressionsent="1">下蝲的示例应用程?/a> 包含一?LDIF 文gQ其中含有预备装载到 LDAP 服务器的用户信息。关于如何将 LDIF 文g导入?LDAP 服务器,请参考第 2 部分?“填充服务?/a>” 一节。注意,该应用程序涉及与W?2 部分相同的用Palice?code>bob ?specialUserQ?br />
  2. 本文下载源代码中的 acegiMethodSecurity.war 文g复制?Tomcat 安装目录中的 webapps 目录?br />
  3. ?Acegi ?jar 文g复制到示例应用程序的 WEB-INF/lib 文g夏V(有关内容请参考第 1 部分?“部v和运行应用程?/a>” 一节?Q?br />
  4. 下蝲 cglib-full-2.0.2.jar 文gq将其复制到CZ应用E序?WEB-INF/lib 文g夏V?

启动 Tomcat q尝试运行示例应用程序?/p>

q行CZ应用E序

通过从浏览器讉K http://localhost:8080/acegiMethodSecurity URL 可调用示例应用程序。AcegiMethodSecurity 昄的烦引页面包含两个链接(Catalog ?LoginQ,如图 2 所C:


?2. CZ应用E序的主面
CZ应用E序的主面

当单d用程序的 Catalog 链接Ӟ它将要求您进行登录。如果以 alice ?specialUser 的n份进行登录,CZ应用E序提?em>完整?/em> cdQ包括公有数据和U有数据。这是因为在 清单 5 中,您对Ҏ安全性拦截器q行了配|,允许用户使用 ROLE_HEAD_OF_ENGINEERING 讉KU有cdQ?alice ?specialUser 都具有该讉K权。另一斚wQ如果您?bob 的n份登录,CZ应用E序仅昄公有数据?/p>



回页?/strong>


为通过w䆾验证的用户分配额外角?/span>

本节演C经q增强的CZ应用E序。增强后的示例应用程序将展示 Acegi 如何使您能够在运行时向通过w䆾验证的用户时分配额外角艌Ӏ?

当安?beanQ例?清单 3 ?privateCatalog beanQ要讉K一个原创资源时Q您可能需要用额外的角色。例如,您可能考虑到您的安?bean 需要通过 Java ?Remote Method Invocation (RMI) 框架或一?Web 服务讉K某个q程应用E序。访问安?bean 的用户不会占用远E应用程序要求访问用h具备的业务角艌Ӏ?/p>

在本例中QAcegi 首先查用h否经q授权来讉K安全 bean。之后,Acegi 允许用户讉K安全 bean。当安全 bean 试图讉Kq程服务Ӟ它需要用额外的业务角色。如果访问安?bean 的用户不具备额外角色Q安?bean ׃能成功访问远E服务?/p>

run-as-replacement 机制

Acegi 框架提供了一U名?run-as-replacement 的简单机Ӟ允许您仅在方法调用期间ؓ通过w䆾验证的用户配|一个或多个额外角色。您可以使用 run-as-replacement 机制问远E应用程序的安全 bean 配置额外角色。这意味着只要安全 bean 需要访问远E应用程序,Acegi ؓ用户装蝲额外角色Q从而允许安?bean 讉Kq程应用E序?/p>

清单 6 ?清单 5 中的Ҏ安全性拦截器的配|进行了增强。增强后的配|用了 run-as-replacement 机制?/p>
清单 6. Acegi Ҏ安全性拦截器的增强配|?/strong>
            <bean id="privateCatalogSecurityInterceptor"
            class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
            <property name="authenticationManager">
            <ref bean="authenticationManager"/>
            </property>
            <property name="accessDecisionManager">
            <ref bean="accessDecisionManager"/>
            </property>
            <property name="runAsManager">
            
<bean id="runAsManager" class="org.acegisecurity.runas.RunAsManagerImpl">
<property name="key"> <value>myKeyPass</value> </property> </bean> </property> <property name="objectDefinitionSource"> <value> sample.PrivateCatalog.getData=ROLE_HEAD_OF_ENGINEERING,RUN_AS_MANAGER </value> </property> </bean>

清单 6 使用_体昄了两处增强(?清单 5 相比Q。第一处增Zؓ runAsManager 属性?code>runAsManager 属性的作用是向通过w䆾验证的用户动态添加角艌Ӏ出于这个目的,runAsManager 属性包含了 RunAsManagerImpl bean 的定义?code>RunAsManagerImpl bean 只有在满下面的条g时才可变为活跃状态:?objectDefinitionSource Ҏ的角色定义中扑ֈ?RUN_AS_ 为前~的角艌Ӏ例如,PrivateCatalog.getData() Ҏ的角色定义(清单 6 中以_体昄的第二处增强Q具有一?RUN_AS_MANAGER 角色?/p>

RunAsManagerImpl bean 包含一个名?key 的属性,它封装的加密键用于确保只额外的角色作ؓ run-as-replacement E序的一部分生成?/p>

当用戯?getData() ҎӞRunAsManagerImpl bean 变ؓz跃状态ƈ创徏名ؓ RUN_AS_MANAGER 的额外角Ԍ从而启?getData() Ҏ讉Kq程应用E序?/p>

增强的方法安全?/span>

本文?下蝲源代?/a> 包含一个名?EnhancedAcegiMethodSecurity 的示例应用程序,它可以演C?run-as-replacement 机制和程序。该应用E序显CZ个具?Catalog 链接的烦引页面。如果单?Catalog 链接Q将要求q行d?/p>

d后,EnhancedAcegiMethodSecurity 应用E序ؓ您提供登录用户及其角色的完整信息。例如,如果?alice ?specialUser w䆾dQ将向您昄用户的所有业务角Ԍ包括额外创徏的时的 RUN_AS_MANAGER 角色?/p>

l束?/span>

在这份共分三部分的系列文章中Q我介绍了如何?Acegi 安全pȝ增强Z URL 的安全性和ZҎ的安全性。您了解了如何设计访问控制策略ƈ它们托在目录服务器中Q如何对 Acegi q行配置以与目录服务器进行通信Q以及如何根据托在服务器的讉K控制{略制定w䆾验证和授权决{?/p>

本系列的最后一文章主要介l用基于方法的安全性保?Java cd例。文章还解释?Acegi ?Spring 如何在内部创建和代理 Java 对象以及 bean 代理如何实现讉K控制。文章包含了两个CZ应用E序Q您可以使用它们q一步研I本pd中学到的概念Q更多有关?Acegi 保护 Java 应用E序的内容,请参?参考资?/a> 节?/p>

来自:http://www-128.ibm.com/developerworks/cn/java/j-acegi3/?

狼爱上狸 2008-05-08 18:47 发表评论
]]>acegi,IBM的Acegi Security SystemQ?Q?http://www.tkk7.com/waterjava/archive/2008/05/08/199311.html狼爱上狸狼爱上狸Thu, 08 May 2008 10:43:00 GMThttp://www.tkk7.com/waterjava/archive/2008/05/08/199311.htmlhttp://www.tkk7.com/waterjava/comments/199311.htmlhttp://www.tkk7.com/waterjava/archive/2008/05/08/199311.html#Feedback0http://www.tkk7.com/waterjava/comments/commentRss/199311.htmlhttp://www.tkk7.com/waterjava/services/trackbacks/199311.html2007 q?6 ?21 ?/p>
了解?Acegi 安全pȝQAcegi Security SystemQ的 基础知识 后,我们介l该pȝ的更加高U的应用。在本文中,Bilal Siddiqui 向您展示了如何结合?Acegi 和一?LDAP 目录服务器,实现灉|的具有高性能?Java™ 应用E序的安全性。还了解如何编写访问控制策略ƈ其存储?ApacheDS 中,然后配置 Acegi 使其与目录服务器交互Q从而实现n份验证和授权的目的?/blockquote>

q期共分三部分的pd文章介绍了如何?Acegi 安全pȝ保护 Java 企业应用E序。在 本系列第一文?/a> 中,我介l了 Acegi q解释了如何使用安全qo器实C个简单的Z URL 的安全系l。在W二文章中Q我讨?Acegi 的更加高U的应用Q首先我编写一个访问控制策略ƈ其存储?ApacheDS 中,ApacheDS 是一个开源的 LDAP 目录服务器。我q将展示配置 Acegi 的方法,使它能够与目录服务器交互q实现您的访问控制策略。本文的l尾提供了一个示例应用程序,它?ApacheDS ?Acegi 实现了一个安全的讉K控制{略?/p>

实现讉K控制{略通常包含两个步骤Q?/p>

  1. 有关用户和用户角色的数据存储在目录服务器中?
  2. ~写安全代码Q它定义有权访问ƈ使用数据的h员?

Acegi 减M码编写的工作Q因此在q篇文章中,我将展示如何用户和用户角色信息存储?ApacheDS 中,然后实现q些信息的访问控制策略。在该系列的最后一文章中Q我展C如何配|?AcegiQ实现对 Java cȝ安全讉K?

您可以在本文的Q何位|?下蝲样例应用E序。参?参考资?/a> 下蝲 Acegi、Tomcat ?ApacheDSQ您需要用它们运行样例代码和CZ应用E序?/p>

LDAP 基础知识

轻量U目录访问协议(Lightweight Directory Access ProtocolQLDAPQ可能是最行的一U定义数据格式的协议Q它针对常见的目录操作,例如对存储在目录服务器中的信息执行的d、编辑、搜索和删除操作。本节将要解释ؓ什么目录服务器是属性文件存储安全信息的首选,q展C如何在 LDAP 目录中组l和托管用户信息?

Z么要使用目录服务器?

本系列第一部分向您介绍了一U简单的ҎQ可以将用户信息以属性文件的形式保存hQ参?W?1 部分Q清?6Q。属性文件以文本格式保存用户名、密码和用户角色。对于大多数真实应用E序而言Q用属性文件存储安全信息远q不够。各U各L理由表明Q目录服务器通常都是更好的选择。其中一个原因是Q真实的企业应用E序可以被大量用戯?—?通常是几千名用户Q如果应用程序将光分功能公开l用户和供应商时更是如此。频J搜索文本文件中随意存储的信息,q样做的效率q不高,但是目录服务器对q类搜烦q行了优化?

W?1 部分的清?6 中的属性文件演CZ另一个原因,该文件组合了用户和角艌Ӏ在真实的访问控制应用程序中Q您通常都需要分别定义和l护用户和角色信息,q样做可以简化用户库的维护。目录服务器为更Ҏ更新用户信息提供了极大的灉|性,例如Q反映职位升q或新聘用h员。参?参考资?/a> 以了解更多关于目录服务器的用及其优点的信息?/p>

LDAP 目录讄

如果希望用户信息存储在一?LDAP 目录中,您需要理解一些有关目录设|的内容。本文ƈ没有提供?LDAP 的完整介l(参见 参考资?/a>Q,而是介绍了一些在试l合使用 Acegi ?LDAP 目录之前需要了解的基本概念?

LDAP 目录以节Ҏ的Ş式存储信息,如图 1 所C:


?1. LDAP 目录的树状结?/strong>
?1. LDAP 目录的树状结? src=

在图 1 中,根节点的名称?org。根节点可以装与不同企业有关的数据。例如,本系列第 1 部分开发的刉业企业被显CZؓ org 节点的直接子节点。该刉业企业h两个名ؓ departments ?partners 的子节点?/p>

partners 子节点封装了不同cd的合作伙伴。图 1 所C的三个分别?customers?code>employees ?suppliers。注意,q三U类型的合作伙伴其行Z企业pȝ用户一栗每一U类型的用户所扮演的业务角色不同,因此讉Kpȝ的权利也不同?

cM圎ͼdepartments 节点包含该制造业企业的不同部门的数据 —?例如 engineering ?marketing 字节炏V每个部门节点还包含一l或多组用户。在 ?1 中,engineers l是 engineering 部门的子节点?/p>

假设每个部门的子节点表示一l用戗因此,部门节点的子节点h不同的用h员。例如,设计部门的所有工E师都是 engineering 部门?engineers l的成员?/p>

最后,注意 ?1 ?departments 节点的最后一个子节点?code>specialUser 是一名用P而非一l用戗在目录讄中,?alice ?bob 之类的用户一般都包含?partners 节点中。我这个特D用户包含在 departments 节点中,以此证明 Acegi 允许用户位于 LADP 目录中Q何地点的灉|性。稍后在本文中,您将了解如何配置 Acegi 以应?specialUser?/p>

使用专有名称

LDAP 使用专有名称QDNQ的概念来识?LDAP 树上特定的节炏V每个节点具有惟一?DNQ它包含该节点完整的层次l构信息。例如,?2 展示了图 1 中的一些节点的 DNQ?/p>
?2. LDAP 目录节点的专有名U?/strong>
?2. LDAP 目录节点的专有名U? src=

首先Q注意图 2 中根节点?DN。它?DN ?dc=orgQ这是与 org 根节点相关的属性值对。每个节炚w有若q个与之相关的属性?code>dc 属性代?“domain component” q由 LDAP RFC 2256 定义Q参?参考资?/a> 中有兛_?RFC 文的链接)QLDAP 目录中的根节炚w常表示Z个域lg?/p>

每个 LDAP 属性是?RFC 定义的。LDAP 允许使用多个属性创Z?DNQ但是本文的CZ只用了以下 4 个属性:

  • dcQ域lgQ?
  • oQ组l)
  • ouQ组l单元)
  • uidQ用?IDQ?

CZ使用 dc 表示域,?o 表示l织名称Q?code>ou 表示l织的不同单元,?uid 表示用户?/p>

׃ org 是根节点Q其 DN 只需指定自n的名Uͼdc=orgQ。比较一下,manufacturingEnterprise 节点?DN ?o=manufacturingEnterprise,dc=org。当向下Ud节点树时Q每个父节点?DN 被包含在其子节点?DN 中?

属性分l?/span>

LDAP 相关的属性类型分到对象类中。例如,名ؓ organizationalPerson 的对象类所包含的属性定义了在组l内工作的h员(例如Q职U、常用名、邮寄地址{等Q?

对象cM用承特性,q意味着 LDAP 定义了基cL保存常用属性。然后子cd对基c进行扩展,使用其定义的属性。LDAP 目录中的单个节点可以使用若干个对象类Q本文的CZ使用了以下几个对象类Q?

  • top 对象cL LDAP 中所有对象类的基cR?br />
  • 当其他对象类都不适合某个对象Ӟ?domain 对象cR它定义了一l属性,M一个属性都可以用来指定一个对象。其 dc 属性是强制性的?br />
  • organization 对象c表C组l节点,例如 ?2 中的 manufacturingEnterprise?br />
  • organizationalUnit 对象c表C组l内的单元,例如 ?1 中的 departments 节点及其子节炏V?

  • groupOfNames 对象c表CZl名Uͼ例如某部门职员的名称。它h一?member 属性,该属性包含一个用户列表?a cmimpressionsent="1">?1 中所有的l节点(例如 engineers 节点Q?member 属性指定该l的成员。而且Q示例?groupOfNames 对象cȝ ouQ组l单元)属性指定组用户的业务角艌Ӏ?br />
  • organizationalPerson 对象c表C组l内某个职员Q例??1 中的 alice 节点Q?




回页?/strong>


使用 LDAP 服务?/span>

在真实的应用E序中,通常有关系l用L大量信息托管在一?LDAP 目录中。例如,存储每个用L用户名、密码、职U、联pL式和工资信息。ؓ单v见,下面的例子将只向您展C如何保存用户名和密码?

如前所qͼCZ使用 ApacheDSQ一U开源的 LDAP 目录服务器)演示?Acegi 是如何?LDAP 目录的。示例还使用了一个开源的 LDAP 客户机(名ؓ JXplorerQ执行简单的目录操作Q例如将信息托管?ApacheDS 上。参?参考资?/a> 以下?ApacheDS、JXplorer q了解更多有关两者协作的信息?

?ApacheDS 创徏一个根节点

要创??1 所C的节点树,必须首先?ApacheDS 中创Z个根节点 org。ApacheDS 为此提供了一?XML 配置文g。XML 配置文g定义了一l可q行配置?beanQ从而根据应用程序的需求定制目录服务器的行为。本文只解释创徏根节Ҏ需的配|?/p>

可以?ApacheDS 安装中的 conf 文gҎ到名?server.xml ?XML 配置文g。打开文g后,会发现很?bean 配置cM?Acegi 的过滤器配置。查扑֐?examplePartitionsConfiguration ?bean。该 bean 控制 ApacheDS 上的分区。当创徏新的根节ҎQ实际上在 LDAP 目录上创Z个新的分区?/p>

~辑 examplePartitionConfiguration bean 以创?org 根节点,如清?1 所C:


清单 1. ~辑模式?examplePartitionConfiguration bean 配置
                        <bean id="examplePartitionConfiguration" class=
            "org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration"
            >
            <property name="suffix"><value>dc=org</value></property>
            <property name="contextEntry">
            <value>
            objectClass: top
            objectClass: domain
            dc: org
            </value>
            </property>
            <!-- Other properties of the examplePartitionConfiguration bean, which you don't
            need to edit. -->
            </bean>
            

清单 1 ~辑?examplePartitionConfiguration bean 的两个属性:

  • 一个属性名?suffixQ它定义Ҏ目的 DN?br />
  • 另一个属性名?contextEntryQ定?org 节点用的对象cR注意,org 根节点用两个对象类Q?code>top ?domain?

本文?源代码下?/a> 部分包含了编辑模式的 server.xml 文g。如果希望l学习本CZQ请?server.xml 文g从源代码中复制到您的 ApacheDS 安装目录中的正确位置Q即 conf 文g夏V?/p>

?3 所C的屏幕截图展示了在 ApacheDS 中创建根节点后,JXplorer 是如何显C根节点的Q?/p>
?3. JXplorer 昄根节?/strong>
?3. JXplorer 昄根节? src=

填充服务?/span>

讄 LDAP 服务器的下一步是使用用户和组信息填充服务器。您可以使用 JXplorer ?ApacheDS 中逐个创徏节点Q但是?LDAP Data Interchange Format (LDIF) 填充服务器会更加方便。LDIF 是可被大多数 LDAP 实现识别的常见格式。developerWorks 文章很好Cl了 LDIF 文g的内容,因此本文不再做详细说明。(参见 参考资?/a> 中有?LDIF 的详l资料。)

您可以在 源代码下?/a> 部分查看 LDIF 文gQ它表示 ?1 所C的用户和部门。您可以使用 JXplorer ?LDIF 文g导入?ApacheDS。要导入 LDIF 文gQ在 JXplorer 中?LDIF 菜单Q如?4 所C:


?4. ?LDIF 文g导入?ApacheDS
?4. ?LDIF 文g导入?ApacheDS

?LDIF 文g导入?ApacheDS 之后QJXplorer 显C用戯点和部门节点树,??1 所C。现在您可以开始配|?AcegiQ其能够与您的 LDAP 服务器通信?/p>



回页?/strong>


?LDAP 实现配置 Acegi

回想一下第 1 部分Q其?Acegi 使用w䆾验证处理qo器(Authentication Processing FilterQAPFQ进行n份验证。APF 执行所有后端n份验证处理Q务,例如从客hh中提取用户名和密码,从后端用户库d用户参数Q以及用这些信息对用户q行w䆾验证?/p>

您在W?1 部分中ؓ属性文件实现配|了 APFQ现在您已将用户库存储在 LDAP 目录中,因此必须使用不同的方式配|过滤器来和 LDAP 目录q行通信。首先看一下清?2Q它展示了在W?1 部分中的 “Authentication Processing Filter” 一节中如何为属性文件实现配|?APF qo器:


清单 2. 为属性文仉|?APF
                        <bean id="authenticationProcessingFilter"
            class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
            <property name="authenticationManager" ref="authenticationManager" />
            <property name="authenticationFailureUrl"
            value="/login.jsp?login_error=1" />
            <property name="defaultTargetUrl"
            value="/index.jsp" />
            <property name="filterProcessesUrl"
            value="/j_acegi_security_check" />
            </bean>
            

查看一下清?2Q您曄?APF 提供?4 个参数。您只需?LDAP 服务器中为存储重新配|第一个参敎ͼauthenticationManagerQ即可。其他三个参C持不变?/p>

配置w䆾验证理?/span>

清单 3 展示了如何配|?Acegi 的n份验证管理器Q以实现?LDAP 服务器的通信Q?/p>
清单 3. ?LDAP 配置 Acegi 的n份验证管理器
                        <bean id="authenticationManager"
            class="org.acegisecurity.providers.ProviderManager">
            <property name="providers">
            <list>
            <ref local="ldapAuthenticationProvider" />
            </list>
            </property>
            </bean>
            

在清?3 中,org.acegisecurity.providers.ProviderManager 是一个管理器c,它管?Acegi 的n份验证过E。ؓ此,w䆾验证理器需要一个或多个w䆾验证提供者。您可以使用理?bean 的提供者属性来配置一个或多个提供者。清?3 只包含了一个提供者,?LDAP w䆾验证提供者?

LDAP w䆾验证提供者处理所有与后端 LDAP 目录的通信。您必须对其q行配置Q下一节内容将讨论该主题?

配置 LDAP w䆾验证提供?/span>

清单 4 展示?LDAP w䆾验证提供者的配置Q?


清单 4. 配置 LDAP w䆾验证提供?/strong>
                        <bean id="ldapAuthenticationProvider"
            class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
            <constructor-arg><ref local="authenticator"/></constructor-arg>
            <constructor-arg><ref local="populator"/></constructor-arg>
            </bean>
            

注意 LDAP w䆾验证提供者类的名UCؓ org.acegisecurity.providers.ldap.LdapAuthenticationProvider 。其构造函数包含两个参敎ͼ使用两个 <constructor-arg> 标记的Ş式,如清?4 所C?/p>

LdapAuthenticationProvider 构造函数的W一个参数是 authenticatorQ该参数通过查用L用户名和密码?LDAP 目录的用戯行n份验证。完成n份验证后Q第二个参数 populator 从 LDAP 目录中检索有兌用户的访问权限(或业务角Ԍ信息?

以下节向您展C如何配|验证器和填充器 bean?





回页?/strong>


配置验证?/span>

authenticator bean 检查具有给定用户名和密码的用户是否存在?LDAP 目录中。Acegi 提供了名?org.acegisecurity.providers.ldap.authenticator.BindAuthenticator 的验证器c,它将执行验证用户名和密码所需的功能?/p>

配置 authenticator beanQ如清单 5 所C:


清单 5. 配置验证?bean
                        <bean id="authenticator"
            class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
            <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>
            <property name="userDnPatterns">
            <list>
            <value>uid={0},ou=employees,ou=partners</value>
            <value>uid={0},ou=customers,ou=partners</value>
            <value>uid={0},ou=suppliers,ou=partners</value>
            </list>
            </property>
            <property name="userSearch"><ref local="userSearch"/></property>
            </bean>
            

在清?5 中,BindAuthenticator 构造函数具有一个参敎ͼ使用 <constructor-arg> 标记的Ş式。清?5 中参数的名称?initialDirContextFactory。该参数实际上是另一?beanQ稍后您学习如何配|该 bean?/p>

目前为止Q只知道 initialDirContextFactory bean 的作用就是ؓE后的搜索操作指定初始上下文。初始上下文是一?DNQ它指定?LDAP 目录内某个节炏V指定初始上下文后,在该节点的子节点中执行所有的搜烦操作Q例如查扄定用P?/p>

例如Q回??2 中查?partners 节点Q它?DN ?ou=partners,o=manufacturingEnterprise,dc=org。如果将 partners 节点指定为初始上下文QAcegi 只?partners 节点的子节点中查扄戗?

指定 DN 模式

除配|?BindAuthenticator 构造函数外Q还必须配置 authenticator bean 的两个属性(清单 5 中的两个 <property> 标记Q?/p>

W一?<property> 标记定义了一?userDnPatterns 属性,它封装了一个或多个 DN 模式列表?em>DN 模式 指定了一l具有类似特性的 LDAP 节点Q例??2 所C的 employees 节点的所有子节点Q?/p>

Acegi 的n份验证器?authenticator bean ?userDnPatterns 属性中配置的每?DN 模式构造了一?DN。例如,查看 清单 5 中配|的W一个模式,?uid={0},ou=employees,ou=partners。在q行w䆾验证的时候,authenticator bean 使用用户提供的用户名Q比?aliceQ替换了 {0}。用用户名取代?{0} 之后QDN 模式变为相?DNQRDNQ?code>uid=alice,ou=employees,ou=partnersQ它需要一个初始上下文才能成ؓ DN?/p>

例如Q查??2 中的 alice's 条目。该条目?employees 节点的第一个子节点。它?DN ?uid=alice,ou=employees,ou=partners,o=manufacturingEnterprise, dc=org。如果?o=manufacturingEnterprise,dc=org 作ؓ初始上下文ƈ其d?RDN uid=alice,ou=employees,ou=partners 之后Q将获得 alice ?DN?/p>

使用q种Ҏ通过 DN 模式构徏了用L DN 后,authenticator 把 DN 和用户密码发送到 LDAP 目录。目录将查该 DN 是否h正确的密码。如果有的话Q用户就可以通过w䆾验证。这个过E在 LDAP 术语中被UCؓ bind w䆾验证。LDAP q提供了其他cd的n份验证机Ӟ但是本文的示例只使用?bind w䆾验证?/p>

如果目录中ƈ没有W一?DN 模式创徏?DNQ?code>authenticator bean 试使用列表中配|的W二?DN 模式。依此类推,authenticator bean 尝试所有的 DN 模式来ؓq行w䆾验证的用h造正的用户 DN?/p>

搜烦qo?/span>

回想一下较早的章节 “LDAP 目录讄”Q我在将用户信息存储?LDAP 目录时添加了一点灵zL。方法是??1 所C的 departments 节点内创Z个特定用PspecialUserQ?/p>

如果试图使用 清单 5 中配|的M一U?DN 模式创徏特定用户?DNQ您会发现没有一U?DN 模式可用。因此,当用户尝试登录时QAcegi ?authenticator bean 不能够构造正的 DNQ从而无法对该用戯行n份验证?/p>

通过允许您指定搜索过滤器QAcegi 能够处理cM的特D情cn份验证器 bean 使用搜烦qo器查找不能够通过 DN 模式构?DN q行w䆾验证的用戗?

清单 5 中的W二?<property> 标记h一?<ref> 子标讎ͼ它引用名?userSearch ?bean?code>userSearch bean 指定搜烦查询。清?6 展示了如何配|?userSearch bean 来处理特定用P


清单 6. 配置搜烦查询以搜索特定用?/strong>
                        <bean id="userSearch"
            class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
            <constructor-arg>
            <value>ou=departments</value>
            </constructor-arg>
            <constructor-arg>
            <value>(uid={0})</value>
            </constructor-arg>
            <constructor-arg>
            <ref local="initialDirContextFactory" />
            </constructor-arg>
            <property name="searchSubtree">
            <value>true</value>
            </property>
            </bean>
            

搜烦查询的参?/strong>

清单 6 展示?userSearch bean ?org.acegisecurity.ldap.search.FilterBasedLdapUserSearch cȝ一个实例,该类的构造函数具有三个参数。第一个参数指?authenticator 在哪个节点中搜烦用户。第一个参数的gؓ ou=departmentsQ该值是一?RDNQ指定了 ?2 所C的 departments 节点?/p>

W二个参?(uid={0}) 指定了一个搜索过滤器。由于?uid 属性指定用P因此可以通过查找 uid 属性具有特定值的节点来查扄戗正如您所料,花括号里面的 0 ?Acegi 表示使用q行w䆾验证的用L用户名(本例中ؓ specialUserQ替?{0}?

W三个参数是对讨?清单 5 中的 BindAuthenticator 构造函数时引入的相同初始上下文的引用。回想一下,当指定了初始上下文后Q稍后将在该初始上下文节点的子节点内q行所有的搜烦操作。注意,应将指定?清单 5 中第一个参敎ͼou=departmentsQ的值的 RDN 前加到初始上下文?/p>

除了q三个构造器参数Q清?6 所C的 userSearch bean q具有一个名?searchSubtree 的属性。如果将其值指定ؓ trueQ搜索操作将包括节点的子树(x有子节点、孙节点、孙节点的子节点{)Q该节点被指定ؓ构造函数的W一个参数的倹{?

authenticator bean 的配|完成后Q下一步将查看 populator bean 的配|,?清单 4 所C?/p>



回页?/strong>


配置 populator

populator bean 读取已l通过 authenticator bean w䆾验证的用L业务角色。清?7 展示 populator bean ?XML 配置Q?/p>
清单 7. populator bean ?XML 配置
                        <bean id="populator"
            class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
            <constructor-arg>
            <ref local="initialDirContextFactory"/>
            </constructor-arg>
            <constructor-arg>
            <value>ou=departments</value>
            </constructor-arg>
            <property name="groupRoleAttribute">
            <value>ou</value>
            </property>
            <property name="searchSubtree">
            <value>true</value>
            </property>
            </bean>
            

在清?7 中,populator bean 的构造函数包?2 个参敎ͼ以及一?groupRoleAttribute 属性。构造函数的W一个参数指定了 populator bean 用来dl过验证用户的业务角色的初始上下文。ƈ不强制要?authenticator ?populator bean 使用相同的初始上下文。您可以两者分别配|一个初始上下文?/p>

W二个构造函数参数指定了 populator 前加到初始上下文?RDN。因此,RDN l成了包含组用户的节点的 DNQ例?departments 节点?/p>

populator bean ?groupRoleAttribute 属性指定了持有l成员业务角色数据的属性。回?讄 LDAP 目录 一节中Q您每l用L业务角色信息存储在名?ou 的属性中。然后将 ou 讄?groupRoleAttribute 属性的|?清单 7 所C?

如您所料,populator bean 搜索整?LDAP 目录来查扄q验证的用户所属的l节炏V然后读取组节点?ou 属性的|获取用户l过授权的业务角艌Ӏ?/p>

q样完成了 populator bean 的配|。目前ؓ止,我们在三个位|用了初始上下文:清单 5?a cmimpressionsent="1">清单 6 ?清单 7。接下来了解如何配|初始上下文?/p>

配置初始上下?/span>

清单 8 展示了在 Acegi 中配|初始上下文的过E:


清单 8. 初始上下文的 XML 配置
                        <bean id="initialDirContextFactory"
            class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
            <constructor-arg value="ldap://localhost:389/o=manufacturingEnterprise,dc=org"/>
            <property name="managerDn">
            <value>cn=manager,o=manufacturingEnterprise,dc=org</value>
            </property>
            <property name="managerPassword">
            <value>secret</value>
            </property>
            </bean>
            

清单 8 ?Acegi 的初始上下文cȝ名称?org.acegisecurity.ldap.DefaultInitialDirContextFactoryQ这?Acegi 包含的工厂类。Acegi 在内部用该cL造其他处理目录操作(例如在整个目录中搜烦Q的cȝ对象。当配置初始上下文工厂时Q必L定以下内容:

  • 您?LDAP 目录和根目录节点的网l地址指定为构造函数的参数。在初始上下文配|的节点作为根节点。就是说所有后l操作(例如 searchQ都在根节点定义的子树中执行?br />
  • ?DN 和密码分别定义ؓ managerDn ?managerPassword 属性。在执行M搜烦操作之前QAcegi 必须使用目录服务器对 DN 和密码进行n份验证?

您已l了解了如何用户库托管?LDAP 目录中,以及如何配置 Acegi 来用来?LDAP 目录的信息对用户q行w䆾验证。下一节将q一步介l?Acegi 的n份验证处理过滤器Q了解新配置?bean 是如何管理n份验证过E的?/p>



回页?/strong>


w䆾验证和授?/span>

APF 配置完成后,能够与 LDAP 目录q行通信来对用户q行w䆾验证。如果您阅读q第 1 部分Q那么对与目录通信q程?APF 执行的一些步骤不会感到陌生,我在W?1 部分中向您展CZqo器如何用不同的服务q行用户w䆾验证。图 5 所C的序列表与您在 W?1 部分?3 看到的非常类|


?5. APF 对一?LDAP 用户q行w䆾验证
?5. APF 对一?LDAP 用户q行w䆾验证

无论 APF 使用属性文件进行内部的w䆾验证q是?LDAP 服务器进行通信Q步?1 到步?9 与第 1 部分是相同的。这里简单描qC?9 个步骤,您可以从步骤 10 开始l学习特定于 LDAP 的事Ӟ

  1. qo器链前面的过滤器请求、响应和qo器链对象传递给 APF?br />
  2. APF 使用取自h对象的用户名、密码和其他信息创徏一个n份验证标记?br />
  3. APF n份验证标C递给w䆾验证理器?br />
  4. w䆾验证理器可能包含一个或多个w䆾验证提供者。每个提供者恰好支持一Un份验证类型。管理器检查哪一U提供者支持从 APF 接收到的w䆾验证标记?

  5. w䆾验证理器将w䆾验证标记传递给适合该类型n份验证的提供者?

  6. w䆾验证提供者从w䆾验证标记中提取用户名q将其传递到名ؓ user cache service 的服务。Acegi ~存了已l进行过w䆾验证的用戗该用户下次dӞAcegi 可以从缓存中加蝲他或她的详细信息Q比如用户名、密码和权限Q,而不是从后端数据存储中读取数据。这U方法得性能得到了改善?br />
  7. user cache service 查用L详细信息是否存在于缓存中?br />
  8. user cache service 用L详细信息q回ln份验证提供者。如果缓存不包含用户详细信息Q则q回 null?br />
  9. w䆾验证提供者检查缓存服务返回的是用L详细信息q是 null?br />
  10. 从这里开始,w䆾验证处理特定于 LDAP?/strong> 如果~存q回 nullQLDAP w䆾验证提供者将把用户名Q在步骤 6 中提取的Q和密码传递给 清单 5 中配|的 authenticator bean?br />
  11. authenticator 用在 清单 5 ?userDnPatterns 属性中配置?DN 模式创徏用户 DN。通过从一?DN 模式中创Z?DNQ然后将?DN 和用户密码(从用戯求中获得Q发送到 LDAP 目录Q它逐一试所有可用的 DN 模式。LDAP 目录检查该 DN 是否存在以及密码是否正确。如果其中Q何一?DN 模式可行的话Q用戯l定?LDAP 目录中,authenticator l执行步?15?

  12. 如果M一U?DN 模式都不能工作的话(q意味着?DN 模式指定的Q何位|都不存在用给定密码的用户Q,authenticator Ҏ 清单 6 配置的搜索查询在 LDAP 目录中搜索用戗如?LDAP 目录没有扑ֈ用户Q那么n份验证以p|告终?br />
  13. 如果 LDAP 目录查找C用户Q它用L DN q回?authenticator?br />
  14. authenticator 用?DN 和密码发送到 LDAP 目录来检查用户密码是否正。如?LDAP 目录发现用户密码是正的Q该用户被l定?LDAP 目录?br />
  15. authenticator 用户信息发送回 LDAP w䆾验证提供者?br />
  16. LDAP w䆾验证提供者将控制权传递给 populator bean?br />
  17. populator 搜烦用户所属的l?br />
  18. LDAP 目录用戯色信息返回给 populator?br />
  19. populator 用戯色信息返回给 LDAP w䆾验证提供者?br />
  20. LDAP w䆾验证提供者将用户的详l信息(以及用户业务角色信息Q返回给 APF。用L在成功进行了w䆾验证?

不论使用何种w䆾验证ҎQ最后三个步骤是相同的(步骤21?1 ?23Q?/p>

配置拦截?/span>

您已l了解了 APF 对用戯行n份验证的步骤。接下来是查看成功进行n份验证的用户是否被授权访问所h的资源。这Q务由 Acegi 的拦截过滤器QInterceptor FilterQIFQ完成。本节将向您展示如何配置 IF 来实现访问控制策略?

回想一下在 W?1 部分的清?7 中配|?IF 的步骤。拦截过滤器在资源和角色之间建立映射Q就是说只有具备必要角色的用h能访问给定资源。ؓ了演C制造业企业中不同部门的业务角色Q清?9 向现有的 IF 配置d了另外的角色Q?/p>
清单 9. 配置拦截qo?/strong>
                        <bean id="filterInvocationInterceptor"
            class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
            <property name="authenticationManager" ref="authenticationManager" />
            <property name="accessDecisionManager" ref="accessDecisionManager" />
            <property name="objectDefinitionSource">
            <value>
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
            /protected/engineering/**=ROLE_HEAD_OF_ENGINEERING
            /protected/marketing/**=ROLE_HEAD_OF_MARKETING
            /**=IS_AUTHENTICATED_ANONYMOUSLY
            </value>
            </property>
            </bean>
            

在清?9 中,IF 包含三个参数。其中第一个和W三个参CW?1 部分中最初配|的参数相同。这里添加了W二个参敎ͼ名ؓ accessDecisionManager ?beanQ?/p>

accessDecisionManager bean 负责指定授权决策。它使用清单 9 中第三个参数提供的访问控制定义来指定授权Q或讉K控制Q决{。第三个参数?objectDefinitionSource?/p>

配置讉K决策理?/span>

accessDecisionManager 军_是否允许一个用戯问某个资源。Acegi 提供了一些访问决{管理器Q它们指定访问控制决{的方式有所不同。本文只解释了其中一U访问决{管理器的工作方式,光|如清单 10 所C:


清单 10. 配置讉K决策理?/strong>
                        <bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
            <property name="decisionVoters">
            <list>
            <bean class="org.acegisecurity.vote.RoleVoter"/>
            <bean class="org.acegisecurity.vote.AuthenticatedVoter" />
            </list>
            </property>
            </bean>
            

在清?10 中,accessDecisionManager bean ?org.acegisecurity.vote.AffirmativeBased cȝ实例?code>accessDecisionManager bean 只包含一个参敎ͼ?em>投票者(voterQ?/em>列表?/p>

?Acegi 中,投票者确定是否允许某个用戯问特定的资源。当使用 accessDecisionManager 查询Ӟ投票者具有三个选项Q允许访问(access-grantedQ、拒l访问(access-deniedQ,如果不确定的话则攑ּ投票Qabstain from votingQ?/p>

不同cd的访问决{管理器解释投票者决{的Ҏ也有所不同。清?10 所C的 AffirmativeBased 讉K决策理器实C单的决策逻辑Q如果Q何投者强制执行肯定投,允许用戯问所h的资源?/p>

投票者逻辑

Acegi 提供了若q个投票者实现类型?code>accessDecisionManager 经q验证的用户的信息(包括用户的业务角色信息)?objectDefinitionSource 对象传递给投票者。本文的CZ使用了两U类型的投票者,RoleVoter ?AuthenticatedVoterQ如清单 10 所C。现在看一下每U投者的逻辑Q?/p>

  • RoleVoter 只有?objectDefinitionSource 对象的行中找C ROLE_ 前缀开头的角色时才q行投票。如?RoleVoter 没有扑ֈq样的行Q将攑ּ投票Q如果在用户业务角色中找C个匹配的角色Q它投给允许讉KQ如果没有找到匹配的角色Q则投票l拒l访问。在 清单 9 中,有两个角色具?ROLE_ 前缀Q?code>ROLE_HEAD_OF_ENGINEERING ?ROLE_HEAD_OF_MARKETING?br />
  • AuthenticatedVoter 只有?objectDefinitionSource 对象中找到具有某个预定义角色的行时才q行投票。在 清单 9 中,有这样一行:IS_AUTHENTICATED_ANONYMOUSLY。匿名n份验证意味着用户不能够进行n份验证。找到该行后Q?code>AuthenticatedVoter 检查一个匿名n份验证的用户是否可以讉K某些不受保护的资源(卌些资源没有包含在具备 ROLE_ 前缀的行中)。如?AuthenticatedVoter 发现所h的资源是不受保护的ƈ?objectDefinitionSource 对象允许匿名w䆾验证的用戯问不受保护的资源Q它投给允许讉KQ否则就投票l拒l访问?




回页?/strong>


CZ应用E序

本文提供了一个示例应用程序,它将演示您目前掌握的 LDAP ?Acegi 概念。LDAP-Acegi 应用E序显CZ个烦引页面,该页面将设计和销售文呈现给合适的l过w䆾验证的用戗正如您看到的一PLDAP-Acegi 应用E序允许用户 alice 查看设计文Qƈ允许用户 bob 查看销售文。它q允许特定用户同时查看设计和销售文。所有这些内定w是在本文开头配|?LDAP 目录服务器时讄的。立?下蝲CZ应用E序 来开始用它?/p>



回页?/strong>


l束?/span>

在本文中Q您了解了如何将用户和业务角色信息托在 LDAP 目录中。您q详l了解了配置 Acegi 的方法,从而与 LDAP 目录交互实现讉K控制{略。在本系列最后一期文章中Q我展C如何配|?Acegi 来保护对 Java cȝ讉K?/p>

来自:http://www.cnblogs.com/amboyna/archive/2008/03/25/1122084.html

狼爱上狸 2008-05-08 18:43 发表评论
]]>acegi,IBM的Acegi Security SystemQ?Q?http://www.tkk7.com/waterjava/archive/2008/05/08/199309.html狼爱上狸狼爱上狸Thu, 08 May 2008 10:41:00 GMThttp://www.tkk7.com/waterjava/archive/2008/05/08/199309.htmlhttp://www.tkk7.com/waterjava/comments/199309.htmlhttp://www.tkk7.com/waterjava/archive/2008/05/08/199309.html#Feedback0http://www.tkk7.com/waterjava/comments/commentRss/199309.htmlhttp://www.tkk7.com/waterjava/services/trackbacks/199309.html2007 q?5 ?08 ?/p>
q䆾共分三部分的pd文章介绍?Acegi 安全pȝQAcegi Security SystemQ,它是用于 Java™ 企业应用E序的强大的开源安全框架。在W一文章中QBilal Siddiqui N向您介l?Acegi 的架构和lgQƈ展示如何使用它来保护一个简单的 Java 企业应用E序?/blockquote>

Acegi Security System 是一U功能强大ƈ易于使用的替代性方案,使您不必再ؓ Java 企业应用E序~写大量的安全代码。虽然它专门针对使用 Spring 框架~写的应用程序,但是Mcd?Java 应用E序都没有理׃M?Acegi。这份共分三部分的系列文章详l介l了 AcegiQƈ展示了如何用它保护单的企业应用E序以及更复杂的应用E序?/p>

本系列首先介l企业应用程序中常见的安全问题,q说?Acegi 如何解决q些问题。您了?Acegi 的架构模型及其安全过滤器Q后者包含了在保护应用程序中用到的大多数功能。您q将了解到各个过滤器如何单独q行工作Q如何将它们l合hQ以及过滤器如何在一个企业安全实C各U功能从头到֜链接h。本文最后通过一个样例应用程序演CZZ URL 安全pȝ?Acegi 实现。本pd后箋两篇文章探I?Acegi 的一些更高的应用,包括如何设计和托访问控制策略,然后如何去配|?Acegi 以用这些策略?/p>

您必?下蝲 AcegiQ这h能编译本文的CZ代码q运行本文的样例应用E序。还必须有作为工作站的一部分q行?Tomcat 服务器?/p>

企业应用E序安全?/span>

׃企业内容理QECMQ应用程序管理存储在不同cd数据源(如文件系l、关pL据库和目录服务)中的企业内容的编写和处理QECM 安全性要求对q些数据源的讉Kq行控制。比如,一?ECM 应用E序可能会控制被授权d、编辑或删除数据的对象,而这些数据和刉业企业的设计、市销、生产以及质量控制有兟?/p>

在一?ECM 安全场景中,比较常见的就是通过对企业资源定位符Q或|络地址Q应用安全性,从而实现访问控制。这U简单的安全模型被称?em>l一资源定位W?/em> ?URL 安全性。正如我在本文后面(以及本系列后l文章)所演示的一PAcegi 为实?URL 安全性提供了全面的特性?/p>

然而,在很多企业场景中QURL 安全性还q远不够。比如,假设一?PDF 文包含某个刉业公司生的特D品的数据。文的一部分包含了将p公司的设计部门编辑和更新的设计数据。另一部分包含了生产经理将使用的生产数据。对于诸如此cȝ场景Q需要实现更加细_度的安全性,Ҏ的不同部分应用不同的访问权限?/p>

本文介绍?Acegi 为实?URL 安全性而提供的各种功能。本pd的下一文章将演示此框架的ZҎ的安全性,它提供了对企业数据访问的更细_度的控制?/p>



回页?/strong>


Acegi Security System

Acegi Security System 使用安全qo器来提供企业应用E序的n份验证和授权服务。该框架提供了不同类型的qo器,可以Ҏ应用E序的需求进行配|。您在本文后面了解?安全qo器的不同cdQ现在,只需注意可以为如下Q务配|?Acegi 安全qo器:

  1. 在访问一个安全资源之前提C用L录?br />
  2. 通过查安全标讎ͼ如密码)Q对用户q行w䆾验证?br />
  3. 查经qn份验证的用户是否h讉K某个安全资源的特权?br />
  4. 成功进行n份验证和授权的用户重定向到所h的安全资源?br />
  5. 对不具备讉K安全资源Ҏ的用hC?Access Denied 面?br />
  6. 在服务器上记录成功进行n份验证的用户Qƈ在用L客户Z讄安全 cookie。用该 cookie 执行下一ơn份验证,而无需要求用户d?br />
  7. n份验证信息存储在服务器端的会话对象中Q从而安全地q行对资源的后箋h?br />
  8. 在服务器端对象中构徏q保存安全信息的~存Q从而优化性能?br />
  9. 当用户退出时Q删除ؓ用户安全会话而保存的服务器端对象?br />
  10. 与大量后端数据存储服务(如目录服务或关系数据库)q行通信Q这些服务用于存储用L安全信息?ECM 的访问控制策略?

正如q个列表昄的那PAcegi 的安全过滤器允许您执行保护企业应用程序所需的几乎Q何事情?/p>



回页?/strong>


架构和组?/span>

?Acegi 了解多Q用v来就简单。这一节介l?Acegi 的组Ӟ接下来您了解该框架如何使用反{控制QIOCQ和 XML 配置文g来组合组件ƈ表示它们的依赖关pR?

四大lg

Acegi Security System 由四U主要类型的lgl成Q过滤器、管理器、提供者和处理E序?/p>

qo?/strong>
q种最高的组件提供了常见的安全服务,如n份验证、会话处理以及注销。我在 本文后面的部?/a> 深入讨论qo器?
理?/strong>
qo器仅是安全相兛_能的高抽象Q实际上要用管理器和提供者实现n份验证处理和注销服务。管理器理׃同提供者提供的较低U的安全服务?
提供?/strong>
有大量的提供者可用于和不同类型的数据存储服务通信Q例如目录服务、关pL据库或简单的内存中的对象。这意味着您可以将用户库和讉K控制协议存储在Q何一U这L数据存储服务中,q且 Acegi 的管理器在q行旉择合适的提供者?
处理E序
有时d可能会被分解为多个步骤,其中每个步骤׃个特定的处理E序执行。比方说QAcegi ?注销qo?/em> 使用两个处理E序来退Z?HTTP 客户机。其中一个处理程序用户?HTTP 会话无效Q而另一个处理程序则删除用户?cookie。当Ҏ应用E序需求配|?Acegi Ӟ多个处理E序能够提供很好的灵zL。您可以使用自己选择的处理程序来执行保护应用E序所需的步骤?

反{控制

Acegi 的组仉过彼此之间的依赖来对企业应用程序进行保护。比如,一个n份验证处理过滤器需要一个n份验证管理器选择一个合适的w䆾验证提供者。这是说您必须能够表示和管?Acegi lg的依赖关pR?

IOC 实现通常用于理 Java lg之间的依赖关pRIOC 提供了两个重要的Ҏ:

  1. 它提供了一U语法,表示应用E序所需的组件以及这些组件如何相互依赖?br />
  2. 它保证了所需的组件在q行时是可用的?

XML 配置文g

Acegi 使用 Spring 框架Q请参见 参考资?/a>Q附带的行开?IOC 实现来管理其lg。Spring 需要您~写一?XML 配置文g来表C组件的依赖关系Q如清单 1 所C:


清单 1. Spring 配置文g的结?/strong>
                        <beans>
            <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
            <property name="filterInvocationDefinitionSource">
            <value> value here </value>
            </property>
            </bean>
            <bean id="authenticationProcessingFilter"
            class="org.acegisecurity.ui.webapp.AuthenticationProcessingFitler">
            <property name="authenticationManager" ref="authManager"/>
            <!-- Other properties -->
            </bean>
            <bean id="authManager"
            class="org.acegisecurity.providers.ProviderManager">
            <property name="providers">
            <!--  List of providers here -->
            </property>
            </bean>
            <!-- Other bean tags -->
            </beans>
            

如您所见,Acegi 使用?Spring XML 配置文g包含一?<beans> 标记Q它装了一些其他的 <bean> 标记。所有的 Acegi lgQ即qo器、管理器、提供者等Q实际上都是 JavaBean。XML 配置文g中的每个 <bean> 标记都代表一?Acegi lg?/p>

q一步解?XML 配置文g

首先注意到的是每个 <bean> 标记都包含一?class 属性,q个属性标识组件所使用的类?code><bean> 标记q具有一?id 属性,它标识作?Acegi lg工作的实例(Java 对象Q?/p>

比方_清单 1 的第一?<bean> 标记标识了名?filterChainProxy 的组件实例,它是名ؓ org.acegisecurity.util.FilterChainProxy 的类的实例?/p>

使用 <bean> 标记的子标记来表C?bean 的依赖关pR比如,注意W一?<bean> 标记?<property> 子标记?code><property> 子标记定义了 <bean> 标记依赖的其?bean 或倹{?/p>

所以在 清单 1 中,W一?<bean> 标记?<property> 子标记具有一?name 属性和一?<value> 子标讎ͼ分别定义了这?bean 依赖的属性的名称和倹{?/p>

同样Q?a cmimpressionsent="1">清单 1 中的W二个和W三?<bean> 标记定义了一个过滤器 bean 依赖于一个管理器 bean。第二个 <bean> 标记表示qo?beanQ而第三个 <bean> 标记表示理?bean?/p>

qo器的 <bean> 标记包含一?<property> 子标讎ͼ该子标记h两个属性:name ?ref?code>name 属性定义了qo?bean 的属性,?ref 属性引用了理?bean 的实例(名称Q?/p>

下一节将展示如何?XML 配置文g中配|?Acegi qo器。在本文后面的内容中Q您在一个样?Acegi 应用E序中用过滤器?/p>



回页?/strong>


安全qo?/span>

正如我前面提到的一PAcegi 使用安全qo器ؓ企业应用E序提供w䆾验证和授权服务。您可以Ҏ应用E序的需要用和配置不同cd的过滤器。这一节将介绍五种最重要?Acegi 安全qo器?/p>

Session Integration Filter

Acegi ?Session Integration FilterQSIFQ通常是您要配置的第一个过滤器。SIF 创徏了一?em>安全上下文对?/em>Q这是一个与安全相关的信息的占位W。其?Acegi qo器将安全信息保存在安全上下文中,也会使用安全上下文中可用的安全信息?/p>

SIF 创徏安全上下文ƈ调用qo器链中的其他qo器。然后其他过滤器索安全上下文q对其进行更攏V比如,Authentication Processing FilterQ我稍后进行介l)用户信息(如用户名、密码和电子邮g地址Q存储在安全上下文中?

当所有的处理E序完成处理后,SIF 查安全上下文是否更新。如果Q何一个过滤器对安全上下文做出了更改,SIF 把更改保存到服务器端的会话对象中。如果安全上下文中没有发CQ何更改,那么 SIF 删除它?/p>

?XML 配置文g中对 SIF q行了配|,如清?2 所C:


清单 2. 配置 SIF
                        <bean id="httpSessionContextIntegrationFilter"
            class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
            

Authentication Processing Filter

Acegi 使用 Authentication Processing FilterQAPFQ进行n份验证。APF 使用一个n份验证(或登录)表单Q用户在其中输入用户名和密码Qƈ触发w䆾验证?/p>

APF 执行所有的后端w䆾验证处理dQ比如从客户求中提取用户名和密码Q从后端用户库中d用户参数Q以及用这些信息对用户q行w䆾验证?

在配|?APF Ӟ您必L供如下参敎ͼ

  • Authentication manager 指定了用来管理n份验证提供者的w䆾验证理器?br />
  • Filter processes URL 指定了客户在dH口中按?Sign In 按钮时要讉K?URL。收到这?URL 的请求后QAcegi 立即调用 APF?br />
  • Default target URL 指定了成功进行n份验证和授权后呈现给用户的页面?br />
  • Authentication failure URL 指定了n份验证失败情况下用户看到的页面?

APF 从用Lh对象中得到用户名、密码和其他信息。它这些信息传送给w䆾验证理器。n份验证管理器使用适当的提供者从后端用户库中d详细的用户信息(如用户名、密码、电子邮件地址和用戯问权利或ҎQ,对用戯行n份验证,q将信息存储在一?Authentication 对象中?/p>

最后,APF ?Authentication 对象保存?SIF 之前创徏的安全上下文中。存储在安全上下文中?Authentication 对象用于做出授权决{?/p>

APF 的配|如清单 3 所C:


清单 3. 配置 APF
                        <bean id="authenticationProcessingFilter"
            class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
            <property name="authenticationManager"
            ref="authenticationManager" />
            <property name="filterProcessesUrl"
            value="/j_acegi_security_check" />
            <property name="defaultTargetUrl"
            value="/protected/protected1.jsp" />
            <property name="authenticationFailureUrl"
            value="/login.jsp?login_error=1" />
            </bean>
            

可以从这D代码中看到QAPF 依赖于上面讨论的q四个参数。每个参数都是作为清?3 所C的 <property> 标记配置的?/p>

Logout Processing Filter

Acegi 使用一?Logout Processing FilerQLPFQ管理注销处理。当客户机发来注销hӞ?LPF q行处理。它标识了来自由客户机所调用 URL 的注销h?/p>

LPF 的配|如清单 4 所C:


清单 4. 配置 LPF
                        <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
            <constructor-arg value="/logoutSuccess.jsp"/>
            <constructor-arg>
            <list>
            <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
            </list>
            </constructor-arg>
            </bean>
            

可以看到 LPF 在其构造方法中包含两个参数Q注销成功 URLQ?code>/logoutSuccess.jspQ和处理E序列表。注销成功 URL 用来在注销q程完成后重定向客户机。处理程序执行实际的注销q程Q我在这里只配置了一个处理程序,因ؓ只需一个处理程序就可以?HTTP 会话变ؓ无效。我在本系列下一文章中讨论更多的处理程序?/p>

Exception Translation Filter

Exception Translation FilterQETFQ处理n份验证和授权q程中的异常情况Q比如授权失败。在q些异常情况中,ETF 决定如何进行操作?/p>

比如Q如果一个没有进行n份验证的用户试图讉K受保护的资源QETF 显CZ个登录页面要求用戯行n份验证。类似地Q在授权p|的情况下Q可以配|?ETF 来呈C?Access Denied 面?/p>

ETF 的配|如清单 5 所C:


清单 5. 配置 ETF
                        <bean id="exceptionTranslationFilter"
            class="org.acegisecurity.ui.ExceptionTranslationFilter">
            <property name="authenticationEntryPoint">
            <bean
            class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
            <property name="loginFormUrl" value="/login.jsp" />
            </bean>
            </property>
            <property name="accessDeniedHandler">
            <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
            <property name="errorPage" value="/accessDenied.jsp" />
            </bean>
            </property>
            </bean>
            

正如清单 5 所C,ETF 包含两个参数Q名?authenticationEntryPoint ?accessDeniedHandler?code>authenticationEntryPoint 属性指定登录页面,?accessDeniedHandler 指定 Access Denied 面?/p>

拦截qo?/span>

Acegi ?em>拦截qo?/em> 用于做出授权决策。您需要在 APF 成功执行w䆾验证后对拦截qo器进行配|,以其发挥作用。拦截器使用应用E序的访问控制策略来做出授权军_?/p>

本系列的下一文章将展示如何设计讉K控制{略Q如何将它们托管在目录服务中Q以及如何配|?Acegi 以读取您的访问控制策略。但是,目前我将l箋向您展示如何使用 Acegi 配置一个简单的讉K控制{略。在本文后面的部分,您将看到使用单的讉K控制{略构徏一个样例应用程序?/p>

配置单的讉K控制{略可分Z个步骤:

  1. ~写讉K控制{略?br />
  2. Ҏ{略配置 Acegi 的拦截过滤器?

步骤 1. ~写单的讉K控制{略

首先看一?清单 6Q它展示了如何定义一个用户及其用戯Ԍ


清单 6. 为用户定义简单的讉K控制{略
                        alice=123,ROLE_HEAD_OF_ENGINEERING
            

清单 6 所C的讉K控制{略定义了用户名 aliceQ它的密码是 123Q角色是 ROLE_HEAD_OF_ENGINEERING。(下一节将说明如何在文件中定义L数量的用户及其用戯Ԍ然后配置拦截qo器以使用q些文g。)

步骤 2. 配置 Acegi 的拦截过滤器

拦截qo器用三个组件来做出授权决策Q我在清?7 中对其进行了配置Q?/p>
清单 7. 配置拦截qo?
                        <bean id="filterInvocationInterceptor"
            class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
            <property name="authenticationManager" ref="authenticationManager" />
            <property name="accessDecisionManager" ref="accessDecisionManager" />
            <property name="objectDefinitionSource">
            <value>
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
            /protected/**=ROLE_HEAD_OF_ENGINEERING
            /**=IS_AUTHENTICATED_ANONYMOUSLY
            </value>
            </property>
            <!--  More properties of the interceptor filter -->
            </bean>
            

如清?7 所C,配置所需的三个组件是 authenticationManager?code>accessDecisionManager?code>objectDefinitionSourceQ?/p>

  • authenticationManager lg与我在介l?Authentication Processing Filter 时讨的n份验证管理器相同。拦截过滤器可以在授权的q程中?authenticationManager 重新对客hq行w䆾验证?br />
  • accessDecisionManager lg理授权q程Q这部分内容在本系列的下篇文章中详l讨论?br />
  • objectDefinitionSource lg包含对应于将要发生的授权的访问控制定义。例如,清单 7 中的 objectDefinitionSource 属性值包含两?URLQ?code>/protected/* ?/*Q。其值定义了q些 URL 的角艌Ӏ?code>/protected/* URL 的角色是 ROLE_HEAD_OF_ENGINEERING。您可以Ҏ应用E序的需要定义Q何角艌Ӏ?br />
    回想一?清单 6Q您为用户名 alice 定义?ROLE_HEAD_OF_ENGINEERING。这是?alice 能够访?/protected/* URL?




回页?/strong>


qo器工作原?/span>

正如您已l了解到的一PAcegi 的组件彼此依赖,从而对您的应用E序q行保护。在本文后面的部分,您将看到如何?Acegi q行配置Q从而按照特定的序应用安全qo器,因此需要创?em>qo器链。出于这个目的,Acegi 保存了一个过滤器铑֯象,它封装了Z护应用程序而配|了的所有过滤器。图 1 展示?Acegi qo器链的生命周期,该周期从客户机向您的应用E序发?HTTP h开始。(?1 昄了服务于览器客h的容器。)


?1. 托管 Acegi qo器链以安全地为浏览器客户机服务的容器
Acegi qo器的生命周期

下面的步骤描qCqo器链的生命周期:

  1. 览器客h向您的应用程序发?HTTP h?br />
  2. 容器接收?HTTP hq创Z个请求对象,该对象将装 HTTP h中包含的信息。容器还创徏一个各U过滤器都可处理的响应对象,从而ؓ发出h的客h准备?HTTP 响应。容器然后调?Acegi 的过滤器链代理,q是一个代理过滤器。该代理知道应用的过滤器的实际顺序。当容器调用代理Ӟ它将向代理发送请求、响应以及过滤器铑֯象?br />
  3. 代理qo器调用过滤器链中W一个过滤器Q向其发送请求、响应和qo器链对象?br />
  4. 链中的过滤器逐个执行其处理。一个过滤器可以通过调用qo器链中下一个过滤器随时l止自n处理。有的过滤器甚至Ҏ不执行Q何处理(比如Q如?APF 发现一个到来的h没有要求w䆾验证Q它可能会立即终止其处理Q?

  5. 当n份验证过滤器完成其处理时Q这些过滤器把h和响应对象发送到应用E序中配|的拦截qo器?br />
  6. 拦截器决定是否对发出h的客hq行授权Q它访问所h的资源?br />
  7. 拦截器将控制权传输给应用E序Q比如,成功q行了n份验证和授权的客hh?JSP 面Q?br />
  8. 应用E序改写响应对象的内宏V?br />
  9. 响应对象已经准备好了Q容器将响应对象转换?HTTP 响应Qƈ响应发送到发出h的客h?br />

为帮助您q一步理?Acegi qo器,我将详细探讨其中两个qo器的操作QSession Integration Filter ?Authentication Processing Filter?/p>

SIF 如何创徏一个安全上下文

?2 展示?SIF 创徏安全上下文所涉及到的步骤Q?/p>
?2. SIF 创徏安全上下?/strong>
SIF 如何创徏安全上下? src=

现在详细地考虑下面q些步骤Q?/p>

  1. Acegi 的过滤器链代理调?SIF q向其发送请求、响应和qo器链对象。注意:通常?SIF 配置滤器链中W一个过滤器?br />
  2. SIF 查它是否已经对这?Web hq行q处理。如果是的话Q它不再进一步进行处理,q将控制权传输给qo器链中的下一个过滤器Q参见下面的W?4 个步骤)。如?SIF 发现q是W一ơ对q个 Web h调用 SIFQ它设|一个标讎ͼ在下一ơ用该标记Q以表示曄调用q?SIF?br />
  3. SIF 检查是否存在一个会话对象,以及它是否包含安全上下文。它从会话对象中索安全上下文Qƈ其攄在名?security context holder 的时占位符中。如果不存在会话对象QSIF 创Z个新的安全上下文Qƈ它攑ֈ security context holder 中。注意:security context holder 位于应用E序的范围内Q所以可以被其他的安全过滤器讉K?br />
  4. SIF 调用qo器链中的下一个过滤器?br />
  5. 其他qo器可以编辑安全上下文?br />
  6. SIF 在过滤器铑֮成处理后接收控制权?br />
  7. SIF 查其他的qo器是否在其处理过E中更改了安全上下文Q比如,APF 可能用戯l信息存储在安全上下文中Q。如果是的话Q它更C话对象中的安全上下文。就是说在过滤器铑֤理过E中Q对安全上下文的M更改现在都保存在会话对象中?

APF 如何对用戯行n份验?/span>

?3 展示?APF 对用戯行n份验证所涉及到的步骤Q?/p>
?3. APF 对用戯行n份验?/strong>
APF 如何对用戯行n份验? src=

现在仔细考虑以下q些步骤Q?/p>

  1. qo器链中前面的qo器向 APF 发送请求、响应和qo铑֯象?br />
  2. APF 使用从请求对象中获得的用户名、密码以及其他信息创n份验证标记?br />
  3. APF n份验证标C递给w䆾验证理器?br />
  4. w䆾验证理器可能包含一个或更多w䆾验证提供者。每个提供者恰好支持一U类型的w䆾验证。管理器查哪一U提供者支持它?APF 收到的n份验证标记?br />
  5. w䆾验证理器将w䆾验证标记发送到适合q行w䆾验证的提供者?br />
  6. w䆾验证提供者支持从w䆾验证标记中提取用户名Qƈ它发送给名ؓ user cache service 的服务。Acegi ~存了已l进行过w䆾验证的用戗该用户下次dӞAcegi 可以从缓存中加蝲他或她的详细信息Q比如用户名、密码和权限Q,而不是从后端数据存储中读取数据。这U方法得性能得到了改善?br />
  7. user cache service 查用L详细信息是否存在于缓存中?br />
  8. user cache service 用L详细信息q回ln份验证提供者。如果缓存不包含用户详细信息Q则q回 null?br />
  9. w䆾验证提供者检查缓存服务返回的是用L详细信息q是 null?br />
  10. 如果~存q回 nullQn份验证提供者将用户名(在步?6 中提取)发送给另一个名?user details service 的服务?

  11. user details service 与包含用戯l信息的后端数据存储通信Q如目录服务Q?

  12. user details service q回用户的详l信息,或者,如果找不到用戯l信息则抛出w䆾验证异常?br />
  13. 如果 user cache service 或?user details service q回有效的用戯l信息,w䆾验证提供者将使用 user cache service ?user details service q回的密码来匚w用户提供的安全标讎ͼ如密码)。如果找C个匹配,w䆾验证提供者将用户的详l信息返回给w䆾验证理器。否则的话,则抛Z个n份验证异常?br />
  14. w䆾验证理器将用户的详l信息返回给 APF。这L户就成功地进行了w䆾验证?br />
  15. APF 用戯l信息保存在 ?2 所C由步骤 3 创徏的安全上下文中?br />
  16. APF 控制权传输l过滤器链中的下一个过滤器?




回页?/strong>


一个简单的 Acegi 应用E序

在本文中Q您已经了解了很多关?Acegi 的知识,所以现在看一下利用您目前学到的知识能做些什么,从而结束本文。对于这个简单的演示Q我设计了一个样例应用程序(参见 下蝲Q,q对 Acegi q行了配|以保护它的一些资源?

样例应用E序包含 5 ?JSP 面Qindex.jsp、protected1.jsp、protected2.jsp、login.jsp ?accessDenied.jsp?/p>

index.jsp 是应用程序的Ƣ迎面。它向用hCZ三个链接,如图 4 所C:


?4. 样例应用E序的欢q页面:
一个简单的 Acegi 应用E序

?4 所C的链接中,其中两个链接指向了被保护的资源(protected1.jsp ?protected2.jspQ,W三个链接指向登录页面(login.jspQ。只有在 Acegi 发现用户没有被授权访问受保护的资源时Q才会显C?accessDenied.jsp 面?/p>

如果用户试图讉KM受保护的面Q样例应用程序将昄d面。当用户使用d面q入后,应用E序自动重定向到被h的受保护资源?/p>

用户可以通过单击Ƣ迎面中的W三个链接直接请求登录页面。这U情况下Q应用程序显C用户可以进入系l的d面。进入系l以后,应用E序用户重定向?protected1.jspQ它是用戯入系l而没有请求特定的受保护资源时昄的默认资源?/p>

配置样例应用E序

为本文下载的源代码包含一个名?acegi-config.xml ?XML 配置文gQ它包含 Acegi qo器的配置。根?安全qo器的讨论 中的CZQ您应该很熟悉这些配|?/p>

我还为样例应用程序编写了一?web.xml 文gQ如清单 8 所C:


清单 8. 样例应用E序?web.xml 文g
                        <web-app>
            <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/acegi-config.xml</param-value>
            </context-param>
            <filter>
            <filter-name>Acegi Filter Chain Proxy</filter-name>
            <filter-class>
            org.acegisecurity.util.FilterToBeanProxy
            </filter-class>
            <init-param>
            <param-name>targetClass</param-name>
            <param-value>
            org.acegisecurity.util.FilterChainProxy
            </param-value>
            </init-param>
            </filter>
            <filter-mapping>
            <filter-name>Acegi Filter Chain Proxy</filter-name>
            <url-pattern>/*</url-pattern>
            </filter-mapping>
            <listener>
            <listener-class>
            org.springframework.web.context.ContextLoaderListener
            </listener-class>
            </listener>
            </web-app>
            

web.xml 文g配置如下Q?/p>

  • acegi-config.xml 文g?URL 位于 <context-param> 标记中?br />
  • Acegi qo器链代理cȝ名称位于 <filter> 标记中?br />
  • URL ?Acegi qo器链代理的映在 <filter-mapping> 标记中。注意:您可以简单地应用程序的所?URLQ?code>/*Q映到 Acegi qo器链代理。Acegi 对映射?Acegi qo器链代理上的所?URL 应用安全性?br />
  • 应用E序上下文加载程序位?<listener> 标记中,它将加蝲 Spring ?IOC 框架?

部vq运行应用程?/span>

部vq运行样例应用程序非常的单。只需要完成两件事情:

  1. ?acegisample.war 文g从本教程下蝲的源代码中复制到安装 Tomcat ?webapps 目录中?br />
  2. ?Acegi Security System 主页 下蝲q解压羃 acegi-security-1.0.3.zip。您找C个名?acegi-security-sample-tutorial.war 的样例应用程序。解压羃 war 文gq提取其 WEB-INF/lib 文g夹中所有的 jar 文g。将所有的 JAR 文g?WEB-INF/lib 文g夹中复制?theacegisample.war 应用E序?WEB-INF/lib 文g夏V?

现在Q您已经行样例应用程序做好准备了。启?Tomcat q将览器指?http://localhost:8080/acegisample/?/p>

您将看到 ?4 所C的Ƣ迎面Q但是此时显C的面是真实的。请l箋q行E序Qƈ查看在尝试访问欢q页面显C的不同链接时会发生什么状c?/p>



回页?/strong>


l束?/span>

?em>使用 Acegi 保护 Java 应用E序 pd的第一文章中Q您了解?Acegi 安全pȝ的特性、架构和lgQ学习了大量有关 Acegi 安全qo器的知识Q这些过滤器被集成到 Acegi 的安全框架中。您q学习了如何使用 XML 配置文g配置lg依赖关系Qƈ查看?Acegi 的安全过滤器在样例程序中工作的情形,该应用程序可以实现基?URL 的安全性?

本文所q的安全技术非常的单,所?Acegi 使用q些技术实现安全性。本pd的下一文章开始介l?Acegi 的一些较为高U的应用Q首先是~写讉K控制协议q将其存储到目录服务中。您q将了解到如何配|?AcegiQ它与目录服务交互Q从而实现您的访问控制策略?/p>




回页?/strong>


下蝲

描述 名字 大小 下蝲Ҏ
本文源代?/th> j-acegi1.zip 10KB HTTP
关于下蝲Ҏ的信?/a>


参考资?

学习

获得产品和技?/strong>

讨论


关于作?/span>

 

Bilal Siddiqui 是一名电子工E师、XML NQ他q是 WaxSysQ主要从事电子商务简化)的创之一。自?1995 q毕业于拉合工E技术大学(University of Engineering and TechnologyQLahoreQ电子工E专业以后,他就开始ؓ工业控制pȝ设计各种软g解决Ҏ。稍后,他致力于 XML 斚wq用他?C++ ~程中取得的l验来构建基?Web ?WAP ?XML 处理工具、服务器端解析方案和服务应用E序。Bilal 是一名技术推q者,q且是一名多产的技术作家?/p>



来自:http://www.cnblogs.com/amboyna/archive/2008/03/25/1122079.html

狼爱上狸 2008-05-08 18:41 发表评论
]]>实战AcegiQ用Acegi作ؓZSpring框架的WEB应用的安全框?/title><link>http://www.tkk7.com/waterjava/archive/2008/05/08/199308.html</link><dc:creator>狼爱上狸</dc:creator><author>狼爱上狸</author><pubDate>Thu, 08 May 2008 10:37:00 GMT</pubDate><guid>http://www.tkk7.com/waterjava/archive/2008/05/08/199308.html</guid><wfw:comment>http://www.tkk7.com/waterjava/comments/199308.html</wfw:comment><comments>http://www.tkk7.com/waterjava/archive/2008/05/08/199308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/waterjava/comments/commentRss/199308.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/waterjava/services/trackbacks/199308.html</trackback:ping><description><![CDATA[<p>最q项目用Acegi作ؓ安全框架的实?效果不错,写了这文章作为ȝ.<br /> <br /> 对于M一个完整的应用pȝQ完善的认证和授权机制是必不可少的。在ZSpringFramework的WEB应用中,<br /> 我们可以使用Acegi作ؓ安全架构的实现。本文将介绍如何在基于Spring构架的Web应用中用AcegiQƈ且详l介<br /> l如何配|和扩展Acegi框架以适应实际需要?br /> </p> <p>文章和代码下?<br /> <br /> <a href="http://www.tkk7.com/Files/youlq/Acegi.zip">http://www.tkk7.com/Files/youlq/Acegi.zip</a><br /> <br /> <br /> <strong><font color="#ff0000">注意Q许多朋友在部v上遇C些麻烦,所以我可以部|的完整的war文g传上来,注意Qjava代码在acegi-sample.war\WEB-INF 目录下,例子需要MysqlQ徏库脚本在acegi-sample.war\db目录下?/font></strong><br /> <br /> <a href="http://www.tkk7.com/Files/youlq/acegi-sample.part1.rar"><font color="#002c99">acegi-sample.part1.rar</font></a><br /> <a href="http://www.tkk7.com/Files/youlq/acegi-sample.part2.rar"><font color="#002c99">acegi-sample.part2.rar</font></a><br /> <a href="http://www.tkk7.com/Files/youlq/acegi-sample.part3.rar"><font color="#002c99">acegi-sample.part3.rar</font></a><br /> <a href="http://www.tkk7.com/Files/youlq/acegi-sample.part4.rar"><font color="#002c99">acegi-sample.part4.rar</font></a><br /> <br /> 附注Q?br /> <br /> 有些朋友询问我如何部|文中的例子Q在此再ơ说明一下(文章中已l有提到Q:<br /> <br /> Mysql的徏表脚本在db目录?br /> Z减小体积Q已l将WEB-INF\lib下的依赖包删除,误行下载以下包Qƈ拯至WEB-INF\lib下:<br /> spring-1.2.4.jar<br /> acegi-security-0.8.3.jar<br /> aopalliance-1.0.jar<br /> c3p0-0.9.0.jar<br /> commons-logging-1.0.4.jar<br /> ehcache-1.1.jar<br /> log4j-1.2.8.jar<br /> mysql-connector-java-3.1.10-bin.jar<br /> oro-2.0.8.jar<br /> <br /> 提示Q?br /> acegi-security-0.8.3.jar<br /> aopalliance-1.0.jar<br /> c3p0-0.9.0.jar<br /> commons-logging-1.0.4.jar<br /> ehcache-1.1.jar<br /> log4j-1.2.8.jar<br /> oro-2.0.8.jar<br /> 可以在acegi-security-0.8.3.zip所带的acegi-security-sample-contacts-filter.war中找到?br /> spring-1.2.4.jar<br /> mysql-connector-java-3.1.10-bin.jar<br /> 要分别到springframework和mysql|站下蝲?/p> <br /> 来自:http://www.tkk7.com/youlq/archive/2005/12/06/22678.html <img src ="http://www.tkk7.com/waterjava/aggbug/199308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/waterjava/" target="_blank">狼爱上狸</a> 2008-05-08 18:37 <a href="http://www.tkk7.com/waterjava/archive/2008/05/08/199308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Acegi的下载和安装http://www.tkk7.com/waterjava/archive/2008/05/08/199307.html狼爱上狸狼爱上狸Thu, 08 May 2008 10:35:00 GMThttp://www.tkk7.com/waterjava/archive/2008/05/08/199307.htmlhttp://www.tkk7.com/waterjava/comments/199307.htmlhttp://www.tkk7.com/waterjava/archive/2008/05/08/199307.html#Feedback0http://www.tkk7.com/waterjava/comments/commentRss/199307.htmlhttp://www.tkk7.com/waterjava/services/trackbacks/199307.html1  Acegi官方发布版的下蝲和安?/h3>

开发者可以通过http://sourceforge.net/projects/acegisecurity或http://acegisecurity.org/下蝲到Acegi官方发布版,比如acegi-security-1.x.zip。图4-4展示了SF中Acegi目的首,它提供了下蝲AcegiQSpring SecurityQ的入口?/p>

?-4  http://sourceforge.net/projects/acegisecurity首页

在单d4-4中的下蝲Q?#8220;Download Acegi Security System for Spring”Q超链接后,开发者进而能够下载到最新的Acegi官方发布包。此Ӟ开发者同时将acegi-security-1.x.zip、acegi-security-1.x-src.zip下蝲到本圎ͼ前者包含了Jar存档和若qAcegi使能应用Q而后者仅仅包含了Acegi目的源代码?/p>

在下载到Acegi官方发布版后Q通过解压acegi-security-1.x.zipQ开发者能够浏览到如图4-5所C的cM内容?/p>

?-5  acegi-security-1.x.zip包含的内?/p>

通常Q大部分Acegi安全性项目仅仅需要用到acegi-security-1.x.jar存档Q这是Acegi的核心包QQ何Acegi使能目都需要用到它。如果项目打采用Java SE 5引入的Annotation注释支持Q则q需要将acegi-security-tiger-1.x.jard到WEB-INF/lib中。如果开发者在使用Acegi提供的容器适配器支持,则还需要将acegi-security-catalina-1.x.jarQ针对TomcatQ、acegi-security-jboss-1.x.jarQ针对JBossQ、acegi-security-jetty-1.x.jarQ针对JettyQ、acegi-security-resin-1.x.jarQ针对ResinQ等Jar存复制到相应的位置Q至于这些Jar包的具体使用Q本书将在第10章详l阐q?/p>

另外Qacegi-security-sample-contacts-filter.war、acegi-security-sample-tutorial.war是两个直接可部v到Java EE容器QTomcat容器Q中的Web应用?/p>

2  Subversion中的Acegi源码下蝲和安?/h3>

如今QAcegiZ码采用Subversion理。开发者通过如图4-6所C的Web面能够获得Subversion下蝲地址Qhttp://sourceforge.net/svn/?group_id=104215Q?/p>

?-6  获得下蝲AcegiZ码地址的Web面

事实上,AcegiQSpring SecurityQ基代码本n是一个Eclipse Java目Q而且它的构徏、管理工作采用了Maven 1.x/2.xQhttp://maven.apache.org/Q。开发者可以借助Eclipse Subversive插g从Subversion存储源获得Acegi的最新基代码。图4-7展示了Subversive内置的SVN Repository Exploring?/p>

?-7  Subversive插g使用截图

一旦在下蝲完成AcegiQSpring SecurityQ基代码后,开发者将能够持箋监控到Acegi目的最新情况,比如获得Acegi持箋更新的基代码、Acegi官方文Q图4-8展示了相应的使用截图?/p>

?-8  持箋更新AcegiZ?/p>

3  有关Acegi的权威去?/h3>

其一Q开发者可以去订阅acegisecurity-developer@lists.sourceforge.net邮g列表Q图4-9展示了订阅这一邮g列表的入口。Acegi开发团队积极参与到q一邮g列表中,因此开发者从q一邮g列表能够获得Acegi的最新进展?/p>

?-9  订阅Acegi开发者邮件列?/p>

其二QAcegi官方论坛Qhttp://forum.springframework.org/Q,?-10展示了论坛截图?/p>

?-10  Acegi官方论坛

开发者可以通过许多渠道获得一手的Acegi知识、开发和部vl验?/p>

5  结

本章围绕AcegiQSpring SecurityQ的认证{略q行了阐qͼ比如Zqo器的设计、与认证源解耦、AcegiSecurityException异常体系{。另外,我们q针对Acegi发布版和Z码的下蝲q行了简要介l?/p>

下章深入到Acegi支持的各U认证机制中?/p>

【参考及推荐资料?/h4>

l  http://acegisecurity.org/

l  http://sourceforge.net/projects/acegisecurity

http://www.polarion.org/index.php?page=overview&project=subversive


来自:http://book.csdn.net/bookfiles/310/10031012826.shtml


狼爱上狸 2008-05-08 18:35 发表评论
]]> վ֩ģ壺 aëƬѸƵ| ۺϾƷվ| ޾ƷĻӰԺ| ޹ƷYW߹ۿ| ƷһƵ | þ㽶Ƶ| ˳վ߹ۿ| 18ͬ־videosվ| ˳ۺ| ձƵ| ëƬaëƬѲ100| שש| 99߹ۿƵ| AV߹ۿɫ| 78˾ƷӰ߲պƷӰһ | һһ| ޸Ƶ| һ| av߹ۿһ | ŷպһ| 91޾Ʒһۺϲ| ޳aƬ777777| ޾ƷƬ߹ۿ| ձaƬѿ| ĻӰԺƵ| ѿ20| ˬAëƬѿ| 97| hƵѹۿ| þþþþҹƷƷ| ҰһƵ| Ѿþˬˬav| ĻƵ| ˿wwwƵ| óav| g0g0ȫѸƵ| ɫѿ| AVһۿ| av뾫Ʒۺ | Ƶ| þòþüƵ7 |