Web service实现和配置
FundsTransferServiceSoapBindingImpl类是Web service实现。其源代码请参见参考资料部分。该类的框架由Axis生成,我们仅仅填写方法来提供实现。请注意该类扩展了ServletEndpointSupport。这是Spring提供的便利类,可以用于JAX-RPC Web service实现,来获取Spring应用程序上下文的引用。通过扩展该类,FundsTransferServiceSoapBindingImpl类可以访问Spring上下文,来获取先前所描述的accountMgr bean的引用。由于FundsTransferServiceSoapBindingImpl类由Axis管理,我们无法使用Spring的依赖性注入工具来自动获取该bean的引用。因此,必须在onInit()方法中明确执行。不幸的是,这会将该类中的一些依赖性添加到特定于Spring的类中。好,这就是使用Spring和Acegi在得到受益的同时需要付出的小小代价。请注意在实际的方法transferFunds()中,代码仅委派给accountMgr bean。
在Axis配置文件(deploy.wsdd和server-config.wsdd)中,需要确保将服务的实现类设置为该类FundsTransferServiceSoapBindingImpl,而不是由Axis生成的其他框架类(FundsTransferServiceSoapBindingSkeleton)。若要使Spring在与Axis相同的web应用程序中正确地工作,我们需要将下面的条目添加到web.xml文件中。context-param条目指定了放置Spring配置文件的位置。listener条目的设置用于在启动时载入Spring配置和上下文。
|
<web-app> <listener> |
Acegi安全配置
现在我们来讨论如何在Spring配置文件中配置Acegi安全。如前所述,我们配置了业务逻辑bean,因此由securityInterceptor bean来侦听方法调用,以执行安全检查。下面我们来看看如何配置该bean。下面所示是securityInterceptor bean的部分Spring配置文件代码。securityInterceptor bean是由名为MethodSecurityInterceptor的Acegi类提供的。正如其名称所示,该类用于加强方法调用的安全,通过侦听调用并检查调用方是否经过认证和授权。
|
<beans> <property name="accessDecisionManager"> <property name="objectDefinitionSource"> |
我们需要配置带有authenticationManager属性的securityInterceptor bean,以指定使用哪种类型的认证。由于我们的设计依靠Axis 处理程序来执行认证,而这里不需要认证,因此仅使用AnonymousAuthenticationProvider进行配置。另外,我们在Axis处理程序中创建认证令牌的方式会使Acegi获知它已经进行了认证,因此不会尝试再次认证。稍后讨论Axis处理程序时,我们将对此进行更加详细的解释。
接下来,我们需要配置带有accessDecisionManager属性的bean,以指定如何决定是否授权某用户进行访问以调用方法。Acegi具有访问决策管理器(access decision manager)的三个具体实现:AffirmativeBased、ConsensusBased和UnanimousBased。Acegi根据投票人对是否授权某用户进行访问以执行特定操作的投票,来实施访问策略。计算投票数来决定是否应该授权访问。我们选择了UnanimousBased访问决策管理器,为了客户端能够执行操作,需要所有的投票都授权访问。用户应该阅读Acegi文档,以获取对该访问决策的更深入说明。下面,我们必须配置带有投票人列表的accessDecisionManager。这里我们仅使用一个名为RoleVoter投票人。这是来自Acegi的类,根据基于角色访问控制对是否授权访问进行投票。用户还应参考Acegi文档,以获取对RoleVoter工作方式的更深入说明。
需要配置的最后一个属性是objectDefinitionSource。这就是如何指定访问受保护的对象上不同方法所需要的认证。在这里,我们只想保护transferFunds()方法,并且只允许访问manager。通过列出所有符合条件的类名、方法名和进行访问所需的角色来实现:
| com.mybank.bizlogic.AccountMgr.transferFunds=ROLE_MANAGER |
定制的Axis处理程序
如先前所描述的,我们需要某个事物来连接Web service安全上下文和Acegi安全上下文。这里即用到定制的Axis处理程序AcegiBridgeAuthenticationHandler。我们保持了非常简单的实现,这样易于解释。可能引起注意的第一件事情是它实际上没有进行任何认证。我们只是从MessageContext中得到用户名和密码,然后照旧使用它们。当然,事实上真正的实现将尝试验证该信息。需要考虑的事情是真正的实现应该从SOAP消息中提取WS-Security头,然后进行处理以得到认证信息,而不是像我们这样仅仅从Axis MessageContext对象中提取他们。
得到认证信息后,接下来就是使其可用于Acegi。通过创建认证令牌,并在Acegi安全上下文中进行设置来实现。由于在进行用户名和密码认证,因此将创建UsernamePasswordAuthenticationToken的实例。进行创建前,需要指定为该主体授予了哪些权限。通过使用GrantedAuthority接口和称为GrantedAuthorityImpl的简单实现来实现。由于使用RoleVoter来进行访问决策,因此我们将进行授权的机构是角色。这里我们再次简化了实现,对其进行硬编码,授权主体manager角色,因为该角色是在POJO上调用transferFunds()方法所需要的。真正的实现可能将获取用户名和密码,然后在数据库或目录服务器中进行查找,以找到与该主体实际相关的角色。或者,在某些情况下,可在WS-Security头中以SAML声明形式获得该信息。
在任何情况下,一旦完成,都将创建UsernamePasswordAuthenticationToken实例,传递用户名、密码和授权的角色。通过使用这种形式的构造方法(采用GrantedAuthority数组),实际上在告知Acegi此令牌已经过了认证,因此不必再次进行认证。接下来,通过在SecurityContextHolder上调用静态方法来得到SecurityContext,并将认证令牌设置到SecurityContext中。现在认证和角色信息对于Acegi是下游可用的,用于执行其安全检查。因此,我们已有效地将Web service安全上下文连接到Acegi安全上下文。
有几件需要考虑的其他事情。首先,Acegi还提供了非常可靠的认证能力,因此不是让Axis处理程序来关注认证,可以让Acegi做这些事情。若要这样做,使用未采用GrantedAuthority数组的构造方法来创建未经认证的认证令牌。用户还需要确保配置了适当的认证提供程序,而不是使用AnonymousAuthenticationProvider。第二,Acegi不仅支持用户名/密码认证,还支持其他认证。例如,如果在进行基于PKI的认证,用户可以使用X509AuthenticationToken,而不是UsernamePasswordAuthenticationToken。
最后,需要配置Axis,在服务的请求处理路径上包含该处理程序。通过向Axis配置文件deploy.wsdd和server-config.wsdd添加以下条目来实现:
|
<deployment xmlns="http://xml.apache.org/axis/wsdd/"xmlns:java="http://xml.apache.org/axis/ <service name="FundsTransferService" provider="java:RPC" style="document" |
结束语
关注点分离是开发面向服务的架构的关键原则。但是,它不仅需要应用到架构级,还需要应用到实现级。在本文中,我们演示了如何使用Axis、Spring和Acegi来实现符合SOA原则的受保护Web service。如示例代码所示,使用该方法使处理每个服务关注点的代码中的交叉依赖性减至最小。我们所给出的示例是刻意保持简单的,但应将其作为基础,用于开发具有可靠安全机制(结合了Web service安全性和Acegi提供的应用程序级安全性)的Web service。如前所述,真正的系统很可能需要开发处理程序,用来处理WS-Security头并将它们连接到Acegi安全上下文。一种方法是采用Apache工具包WSS4J,然后扩展其Axis处理程序以填充Acegi安全上下文,如本文所述。可能需要进行一些其他工作来创建捕获Acegi安全异常的Axis出站处理程序,并创建返回到客户端的更有意义的SOAP错误。
(责任编辑:铭铭 mingming_ky@126.com TEL:(010)68476636)
| 共2页: 上一页 [1] 2 | ||
|