`
suli
  • 浏览: 44598 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

ONJava.com -- Web 服务实现中的概念分离 --> page 1

阅读更多

Web 服务实现中的概念分离

作者 Tieu Luu 09/06/2006
翻译 Judy01/29/2007

概念分离是面向服务体系结构的一项核心原则。 不幸的是,在实现 SOA 服务时,这项原则总是被忽略。 经常可以看到一个很长的类具有多重概念,例如安全、事务管理和登录等全部与业务逻辑混杂在一起。 使用 Spring 框架Aspect Oriented Programming (AOP) 准则,可以将概念分离灌输到服务实现中去。

在这篇文章中, 我将介绍如何使用 Apache Axis 和 Spring 开发 Web 服务,以及使用 Acegi Security 保证服务的安全 -- 从始至终都可以保持概念可以很好地分离。

动机与设计

本文使用的示例服务称作 FundsTransferService,使用此服务银行可以将资金从一个帐户转移到另一个帐户。 服务的 WSDL、所有的源代码、配置文件和生成文件已在本文的资源部分给出。 我们有意选择一个简单的服务,目的是把重点放在文章的其他方面。 在此服务的实现过程中,将遇到三个概念:

  • Web 服务引流,将其功能作为服务公开
  • 业务逻辑,以执行转移资金
  • 确保安全性,只有授权者可以执行资金转移

一个实际的系统还极有可能处理其他的概念,如事务管理、登录等。

服务实现的设计目标是,需要将特定的代码应用于特定的概念,而且概念与概念相互独立。 对于 Web 服务引流,我们使用 Axis 将其功能公开为一个服务。 跨帐户的资金转移这一业务逻辑,则将其封装在一组传统纯 Java 对象 (Plain Old Java Object,POJO) 中。 而安全性将由 Acegi Security 框架提供。 我们将使用 Spring 框架及其 AOP 功能将所有内容捆扎在一起,使实现此 Web 服务的代码间的依赖性降低。

实现的设计如图 1 所示。黄色是我们将要实现的对象。 蓝色由 Axis 提供,粉色由 Acegi 提供,绿色由 Spring 提供。 FundsTransferService WSDL 中设计的服务的接口。 为简化此图,我们将所有 Axis 类视为组件,称为 Axis EngineBasicHandler 也是一个 Axis 类,但是由于它对设计的重要性我们还需要特殊对待(稍后详细讨论)。 FundsTransferServiceSoapBindingImpl 是 Axis 生成的类,也是我们需要加以实现以便提供服务的功能。 它将通过 Spring 间接为业务逻辑 POJO AccountMgrImpl 对象服务。(稍后也将详加讨论。) AccountMgrImplAccountMgr 接口包装在一起,因为这是一个很好的做法,还因为这允许 Spring 发挥它的神奇作用(还有另外一种方法是在不使用接口的情况下使用 Spring)。


图 1. 实现资金转移服务的设计

现在回到 BasicHandler。 需要它的原因是它关系到我们已选择的提供安全保障的方式。 在此示例中,我们将处理两个层次上的安全性:Web 服务的安全性,和应用程序代码的安全性,例如,POJO。 对于概念分离的思想,我们已经提出了一个方案。 Axis 允许使用自定义的事务处理程序,以便截取提供其他如安全性等功能的请求和响应消息。 因此,我们将创建一个自定义的事务处理程序,称之为AcegiBridgeAuthenticationHandler,用于负责处理 Web 服务安全。 它扩展自 Axis 的 BasicHandler 类,因此可以将其插入 Axis 处理程序的框架。 Acegi 将用于提供应用程序级别的安全,例如,提供对 POJO 的访问控制。

要使二者协同无缝地工作,我们需要将 Web 服务安全上下文过渡到 Acegi 安全上下文,因此将自定义的 Axis 处理程序类命名为 AcegiBridgeAuthenticationHandler。 它不仅会处理 Web 服务安全的流程,还负责将从该流程中获取的安全上下文过渡到 Acegi 环境中,以便 Acegi 来决定授权,是否允许访问 POJO。 这是通过从 Web 服务请求消息中提取安全性设置完成的,Acegi 将验证请求,然后创建一个授权标识,即 UsernamePasswordAuthenticationToken,因为在本示例中我们已经选择使用“用户名/密码”式的授权方式。 然后,将授权标识添加到 Acegi 的 SecurityContext 中,这样一来请求中的授权信息和权限在 Acegi 控制业务逻辑的 POJO 时就可供使用了。

现在开始解释如何使用 Spring 将所有内容捆扎在一起。 其妙处就在于图 1 中名为 AOP proxy 的那个绿色对象,它是由 Spring 生成的。 这个对象实现了 AccountMgr 接口,行为上相当于业务逻辑 POJO AccountMgrImpl 的代理。 这允许 Spring 插入 Acegi 的 AccountMgrImpl 来执行访问控制,以检查何时在 POJO 上发生方法调用。 当 FundsTransferServiceSoapBindingImpl 向 POJO 发出 Web 服务请求时,它实际上是向一个 AOP 代理的实例发出的而不是直接针对 AccountMgrImpl。 因为 FundsTransferServiceSoapBindingImpl 扩展了 ServletEndpointSupport,所以它可以访问 Spring 应用程序上下文来获取一个对 AOP 代理(已经使用合适的接口、拦截器和目标类 AccountMgrImpl 进行了配置)的引用。

图 2 的序列图中展示了当客户端调用 FundsTransferService 时将发生的流程。 Axis Engine 将负责接收请求消息,然后激活 AcegiBridgeAuthenticationHandlerAcegiBridgeAuthenticationHandler 验证授权信息,然后创建一个 UsernamePasswordAuthenticationToken。 接下来,它将该标识写入 SecurityContext 以便 Acegi 将来使用。 AcegiBridgeAuthenticationHandler 成功返回后,Axis Engine 就会调用 FundsTransferServiceSoapBindingImpl 上的 transferFunds() 方法。 FundsTransferServiceSoapBindingImpl 将它委托给 AOP proxy,该代理是 FundsTransferServiceSoapBindingImpl 早在从 Spring Web 应用程序上下文进行初始化时就已经获取的。 AOP proxy 调用 Acegi MethodSecurityInterceptor 以便执行安全性检查。 MethodSecurityInterceptorSecurityContext 处获取授权标识并检查是否被授权。 然后,使用授权标识中的信息,来查看客户端是否被允许调用 AccountMgrImpl 上的 transferFunds() 方法。 如果许可访问,则 MethodSecurityInterceptor 允许调用该方法进行 AccountMgrImplAccountMgrImpl 最终处理请求并返回结果,结果最终被传送到客户端程序。


图 2。服务实现的处理流程序列图

1, 2, 3, 4

下一页箭头



评论

相关推荐

Global site tag (gtag.js) - Google Analytics