使用Acegi保护JSF应用程序

开发 后端
本文介绍使用Acegi保护JSF应用程序,以及深入探讨Acegi和JSF组件,并澄清一些关于使用Acegi和JSF的常见误解。

如何使用 Acegi 保护在 servlet 容器中运行的 JavaServer Faces (JSF) 应用程序。本文首先解释 Acegi 针对此目标提供的特性,并澄清一些关于使用 Acegi和JSF 的常见误解。然后提供一个简单的 web.xml 文件,可以用来部署 Acegi,从而保护 JSF应用程序。然后深入探讨 Acegi和JSF 组件,了解在部署 web.xml 文件和用户访问 JSF应用程序时所发生的事件。本文最后提供了一个由 Acegi 保护的示例 JSF应用程序。

无需编写 Java 代码即可添加安全性

回顾一下本系列的第一个示例 Acegi 应用程序(请参阅 第 1 部分 中的 “一个简单 Acegi 应用程序” 一节)。该应用程序使用 Acegi 提供了以下安全特性:
◆当一个未经验证的用户试图访问受保护的资源时,提供一个登录页面。
◆将授权用户直接重定向到所需的受保护资源。
◆如果用户未被授权访问受保护资源,提供一个访问拒绝页面。

回想一下,您无需编写任何 Java 代码就能获得这些特性。只需要对 Acegi 进行配置。同样,在 JSF应用程序中,无需编写任何 Java 代码,也应该能够从 Acegi 实现相同的特性。

澄清误解

其他一些作者似乎认为将 Acegi 与 JSF 集成需要 JSF应用程序提供登录页面(参见 参考资料)。这种观点并不正确。在需要时提供登录页面,这是 Acegi 的职责。确保登录页面在安全会话期间只出现一次,这也是 Acegi 的职责。然后,经过身份验证和授权的用户可以访问一个受保护资源,无需重复执行登录过程。

如果使用 JSF 提供登录页面,将会发生两个主要的问题:
◆当需要时,没有利用 Acegi 的功能提供登录页面。必须编写 Java 代码实现所有逻辑来提供登录页面。
◆至少需要编写一些 Java 代码将用户凭证(用户名和密码)从 JSF 的登录页面移交到 Acegi。

Acegi 的目的是避免编写 Java 安全代码。如果使用 JSF 提供登录页面,则没有实现这一用途,并且会引发一系列其他 JSF-Acegi 集成问题,所有这些问题都源于 “Acegi 是用来提供可配置安全性” 这一事实。如果试图使用 JSF 来完成 Acegi 的工作,将会遇到麻烦。

本文余下部分将解释并演示独立于 Acegi 的 JSF应用程序开发,并在稍后配置 Acegi 以保护 JSF应用程序 — 无需编写任何 Java 代码。首先看一下 web.xml 文件,可以部署该文件保护 JSF应用程序。

部署 Acegi 保护 JSF应用程序

清单 1 展示了一个 web.xml 文件(通常称为部署描述符),可以使用这个文件部署 Acegi,从而保护运行在 servlet 容器(比如 Apache Tomcat)中的 JSF应用程序:

清单 1. 用于部署 Acegi 和 servlet 容器中的 JSF 的 web.xml 文件

  1. <?xml version="1.0"?> 
  2. <!DOCTYPE web-app PUBLIC-//Sun Microsystems, Inc.//DTD 
    Web Application 2.3//EN http://java.sun.com/dtd/web-app_2_3.dtd"
    > 
  3. <web-app> 
  4. <context-param> 
  5. <param-name>contextConfigLocation</param-name> 
  6. <param-value>/WEB-INF/acegi-config.xml</param-value> 
  7. </context-param> 
  8. <context-param> 
  9. <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
  10. <param-value>server</param-value> 
  11. </context-param> 
  12. <context-param> 
  13. <param-name>javax.faces.CONFIG_FILES</param-name> 
  14. <param-value>/WEB-INF/faces-config.xml</param-value> 
  15. </context-param> 
  16. <listener> 
  17. <listener-class> 
  18. org.springframework.web.context.ContextLoaderListener  
  19. </listener-class> 
  20. </listener> 
  21. <listener> 
  22. <listener-class> 
  23. com.sun.faces.config.ConfigureListener  
  24. </listener-class> 
  25. </listener> 
  26. <!-- Faces Servlet --> 
  27. <servlet> 
  28. <servlet-name>Faces Servlet</servlet-name> 
  29. <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
  30. <load-on-startup> 1 </load-on-startup> 
  31. </servlet> 
  32. <!-- Faces Servlet Mapping --> 
  33. <servlet-mapping> 
  34. <servlet-name>Faces Servlet</servlet-name> 
  35. <url-pattern>*.faces</url-pattern> 
  36. </servlet-mapping> 
  37. <!-- Acegi filter configuration --> 
  38. <filter> 
  39. <filter-name>Acegi Filter Chain Proxy</filter-name> 
  40. <filter-class> 
  41. org.acegisecurity.util.FilterToBeanProxy  
  42. </filter-class> 
  43. <init-param> 
  44. <param-name>targetClass</param-name> 
  45. <param-value> 
  46. org.acegisecurity.util.FilterChainProxy  
  47. </param-value> 
  48. </init-param> 
  49. </filter> 
  50. <!-- Acegi Filter Mapping --> 
  51. <filter-mapping> 
  52. <filter-name>Acegi Filter Chain Proxy</filter-name> 
  53. <url-pattern>/*</url-pattern> 
  54. </filter-mapping> 
  55. </web-app> 

注意,清单 1 包含以下标记:
◆3 个 <context-param> 标记
◆2 个 <listener> 标记
◆1 个 <filter> 标记
◆1 个 <servlet> 标记
◆1 个 <servlet-mapping> 标记
◆1 个 <filter-mapping> 标记

阅读该文件,了解每个标记在 JSF-Acegi 应用程序中的用途。

向 Acegi和JSF 提供上下文参数

清单 1 中的每个 标记定义一个参数,供 Acegi 或 JSF 在启动或执行期间使用。第一个参数 — contextConfigLocation — 定义 Acegi 的 XML 配置文件的位置。

JSF 需要 javax.faces.STATE_SAVING_METHOD 和 javax.faces.CONFIG_FILES 参数。javax.faces.STATE_SAVING_METHOD 参数指定希望在客户机还是服务器上存储 JSF 页面-视图状态。Sun 的参考实现的默认行为是将 JSF 视图存储在服务器上。

javax.faces.CONFIG_FILES 参数指定 JSF 需要的配置文件的位置。JSF 配置文件的详细信息不属于本文讨论的范围(参见 参考资料,获取涉及该主题的资源链接)。

为 Acegi和JSF 配置侦听器

现在看一下 清单 1 中的 2 个 标记。 标记定义侦听器类,侦听器类侦听并处理 JSP 或 servlet 应用程序启动和执行期间发生的事件。例如:
◆启动 JSP 或 servlet 应用程序时servlet容器创建一个新的 servlet 上下文。每当 JSP 或 servlet 应用程序启动时,就会触发此事件。
◆servlet 容器创建一个新的 servlet 请求对象。每当容器从客户机收到一个 HTTP 请求时,此事件就会发生。
◆建立一个新的 HTTP 会话。当请求客户机建立一个与 servlet 容器的会话时,此事件就会发生。
◆一个新属性被添加到 servlet 上下文、servlet 请求和 HTTP 会话对象。
◆servlet 上下文、servlet 请求或 HTTP 会话对象的一个现有属性被修改或删除。

标记就像一种可扩展性机制,允许在 servlet 容器内部运行的应用程序协同某些事件进行处理。servlet 规范定义了侦听器类为处理事件而实现的一些接口。

例如,Spring Framework 实现一个 javax.servlet.ServletContextListener servlet 接口。实现此接口的 spring 类是 org.springframework.web.context.ContextLoaderListener。注意,这是 清单 1 的第一个 标记中的侦听器类。

类似地,JSF 实现一个 com.sun.faces.config.ConfigureListener 类,该类实现一些事件-侦听接口。可以在 清单 1 的第二个 标记中找到 ConfigureListener 类。

本文稍后将解释不同的事件-侦听器接口,以及 Acegi和JSF 事件-侦听器类内部执行的处理(请参阅 “启动 JSF-Acegi 应用程序” 和 “处理对受 Acegi 保护的 JSF 页面的请求”)。

配置和映射 servlet 过滤器

现在看一下 清单 1 中的 标记。在请求的 servlet 处理传入的请求之前,servlet 应用程序使用过滤器对其进行预处理。在请求执行之前,Acegi 使用 servlet 过滤器对用户进行身份验证。

请注意 清单 1 中的 标记,它的 子标记指定一个 org.acegisecurity.util.FilterToBeanProxy 类。FilterToBeanProxy 类是 Acegi 的一部分。此类实现一个 javax.servlet.Filter 接口,该接口是 servlet 应用程序的一部分。javax.servlet.Filter 接口有一个 doFilter() 方法,servlet 容器在收到请求时调用该方法。

还需注意,清单 1 的 标记有另一个子标记 标记指定实例化 FilterToBeanProxy 类所需的参数。可以从 清单 1 中看出,FilterToBeanProxy 类只需要一个参数,该参数是 FilterChainProxy 类的一个对象。FilterChainProxy 类表示 第 1 部分 1 中讨论的整个 Acegi 过滤器链(请参阅 “安全过滤器” 小节)。FilterToBeanProxy 类的 doFilter() 方法使用 FilterChainProxy 类执行 Acegi 的安全过滤器链。

清单 1 中的 标记指定调用 Acegi 的 FilterToBeanProxy 的请求 URL。我已经将所有的 JSF 页面映射到 Acegi 的 FilterToBeanProxy。这意味着只要用户试图访问 JSF 页面,FilterChainProxy doFilter() 方法就会自动获得控制权。

配置 JSF servlet

web.xml 文件中的 标记指定希望从特定 URl 调用的 servlet(在本例中是一个 JSF servlet)。 标记定义该 URL。几乎所有的 JSP 或 servlet 应用程序都包含这两个标记,所以无需再作讨论(参见 参考资料,获取讨论 servlet 编程的资源链接)。

现在,您已经看到,web.xml 文件要部署 Acegi 以保护 JSF 应用程序所需的所有标记。您已经了解了侦听器、过滤器和 servlet 如何相互协作。从这里的讨论中可以看出,如果在 servlet 容器中部署 清单 1 中的 web.xml 文件,Acegi和JSF 都试图在两种情形下进行一些处理:
◆当启动应用程序时
◆当应用程序收到对 JSF 页面的请求时

【编辑推荐】

  1. JSF的技术与组件
  2. 学习JSF程序入门
  3. Ajax优于JSF的几个原因讨论
  4. JSF开发问题和解决
  5. Java学习笔记-JSF
责任编辑:佚名 来源: cnblogs
相关推荐

2009-06-24 10:34:39

JSF生命周期JSF应用程序

2009-07-14 16:40:31

MyEclipse开发

2009-06-22 16:19:40

Acegi安全系统JSF

2022-08-30 20:00:37

零信任Linkerd

2011-03-30 13:28:26

2020-08-25 14:03:20

应用程序屏蔽应用程序内保护网络攻击

2021-10-11 09:00:00

云原生Kubernetes安全

2009-06-29 13:44:07

Rational ApAjax和JSFWeb

2024-02-28 07:40:13

ConfuserEx代码工具

2022-02-16 12:03:02

区块链移动应用数字交易

2011-08-18 09:47:42

2010-08-04 09:43:28

Flex应用程序

2010-05-06 13:49:11

2011-02-22 10:23:43

2012-03-09 17:30:28

ibmdw

2011-12-22 10:30:49

2021-06-08 09:00:00

安全WebTLS

2011-11-30 21:56:31

ibmdwXPathPHP

2022-09-26 14:07:38

云原生NVMe存储

2010-12-15 16:17:59

服务部署
点赞
收藏

51CTO技术栈公众号