Web服务安全性(WS-Security)是OASIS标准,描述了如何使用Web服务实现消息级安全性。 具体地说,WS-Security描述了如何在SOAP消息中添加机密性(例如加密),完整性(例如数字签名)以及传播用于身份验证的安全性令牌(例如用户名和密码)。 但是,WS-Security规范允许在SOAP消息中同时发送多个安全令牌,并且通常Java™平台企业版(JEE)Web服务提供程序实现基于来自安全令牌之一的主体(身份)执行授权检查。 在本文中,我们将描述如何配置WebSphere以选择SOAP消息的哪个安全令牌作为JEE主体,可用于授权决策。
请注意,JEE安全模型支持Web容器和EJB容器的声明性安全授权以及编程安全性。 使用Web容器编程API(例如getUserPrincipal()
)和EJB容器编程API(例如getCallerPrincipal()
)之间存在细微的差异。 但是,本文的范围是讨论如何配置Web服务,以指定应将SOAP标头中的令牌之一用作JEE主体。 设置此主体后,您可以像往常一样简单地使用JEE安全模型和WebSphere Base Security API。
您可以声明性地或以编程方式使用JEE安全模型对servlet和EJB进行授权。 但是,出于本文的目的,我们将演示一个基于Servlet的Web服务,该服务使用编程JEE API来获取主体。 您可以扩展该示例以使用JEE编程API在基于servlet的基础Web服务提供程序中执行编程授权检查,或者为EJB配置基于JEE角色的方法级安全性。 Web容器以及EJB容器的JEE声明性和程序性安全性将在其他材料中介绍,而不是本文的重点。 (请参阅相关主题以获取更多信息)。我们的目标是展示如何启用与WebSphere Application Server上的JEE授权框架使用消息级安全令牌的集成。
创建一个JAX-WS服务提供者
- 使用Rational Application Developer(Application Developer)V7.5.2,创建一个新的动态Web项目,其项目名称为
HelloWorldProject
。 - 接下来,创建一个名为
HelloWorldProvider
的新Java类,并将清单1的内容复制到该新类中。清单1. HelloWorldProvider.java
package com.ibm.dwexample; import javax.annotation.Resource; import javax.jws.WebService; import javax.xml.ws.WebServiceContext; @WebService public class HelloWorldProvider { @Resource WebServiceContext wsCtx; public String sayHello(String msg) { System.out.println("[provider] received " + msg); System.out.println("[provider] user = " + wsCtx.getUserPrincipal()); return "Hello " + msg; } }
HelloWorldProvider代码中有趣的部分是
@Resource WebServiceContext
。 此行允许JAX-WS运行时注入Web服务上下文,并使您能够从上下文访问JEE主体。 但是,为了使此代码实际在Application Server中返回正确的主体,必须在服务提供者绑定中配置Caller。 否则,您可能会得到“主体:/ UNAUTHENTICATED *”的结果。 - 右键单击HelloWorldProject,然后选择Run As => Run on Server 。 确保在“ WebSphere Application Server的发布设置”部分中选择了“使用服务器上的资源运行服务器” 。
- 选择一个WebSphere Application Server v7.0服务器概要文件,然后单击Finish 。
保护服务提供商
策略集和策略集绑定在第1部分中进行了介绍,因此我们将直接创建一个策略集,该策略集将用于指定UsernameToken作为Web服务的身份验证令牌。 创建此策略集并将其附加到服务提供者后,您将创建服务器端绑定,在其中您将指定将哪个令牌用作主要安全令牌,即JEE主体。 您需要执行此操作,因为WS-Security规范允许附加多个令牌进行身份验证,因此需要其他元数据来标识哪个是主要安全令牌。 在WebSphere中,此元数据称为“调用者”,并被配置为WS-Security绑定的一部分,如我们在本文中将展示的那样。
我们将使用Application Server管理控制台来创建策略集,将该策略集附加到您的服务提供商,并创建该服务提供商将遵循的绑定。
- 在Application Developer中,在Servers视图中右键单击Application Server V7运行时,然后选择Administration => Run管理控制台 ,如图1所示。
图1.启动管理控制台
- 从管理控制台中,选择Services => Policy sets => Application policy sets ,如图2所示。
图2.应用程序策略集
- 单击“ 新建”以创建新的策略集。
- 将
My UNT
指定为新策略集的名称,并在Description字段中添加描述,然后单击Apply 。 - 接下来,在Policys部分中单击Add ,然后选择WS-Security作为要添加的策略,如图3所示。
图3.新策略集
- 将策略添加到新策略集中后,只需单击WS-Security即可对其进行配置。
- 点击主策略 ; 您应该看到一个类似于图4的屏幕。
图4.配置WS-Security策略
- 默认情况下,WS-Security策略是使用消息级保护创建的,如第1部分中所述。 但是,为了简化本文的操作,请取消选中“ 消息级别保护” ,然后单击“ 应用 ”,以禁用消息级别保护。
- 由于我们的策略需要UsernameToken来提取JEE主体,因此您需要通过执行以下操作将UsernameToken添加到WS-Security策略:
- 在主策略的“ 策略详细信息”部分中,单击“ 请求令牌策略”。
- 单击Add Token Type,然后选择UserName ,如图5所示。
图5.将UsernameToken添加到请求令牌策略
- 为用户名令牌指定
MyUsernameToken
,然后将WS-Security 1.0保留为WS-Security版本,如图6所示,然后单击Apply 。图6.指定UsernameToken
- 单击保存将更改直接保存到主配置。 您应该看到一个类似于图7的屏幕。
图7.配置的UsernameToken策略
- 现在已经创建了策略集,您需要将其附加到服务提供商。 从管理控制台中,选择Services => Service provider以获取JAX-WS服务提供者的列表,然后选择HelloWorldProviderService ,如图8所示。
图8. JAX-WS服务提供者
- 选中HelloWorldProviderService ,单击“ 附加策略集” ,然后选择您的策略集(例如, My UNT )。
- My UNT策略集现在已附加到HelloWorldProviderService上,如图9所示。
图9.将策略集附加到服务提供商
- 策略集指定“内容”,而绑定指定“方式”。 因此,您需要为此服务提供商配置策略集绑定。 去做这个:
- 检查HelloWorldProviderService ,然后单击“ 分配绑定” ,然后选择“ 新建应用程序特定绑定” 。
- 将
ServerUNTBinding
指定为Bindings配置名称 ,然后单击Add并选择WS-Security以创建应用程序特定的绑定,如图10所示。图10.策略集绑定配置
请注意,绑定分配检查了策略集,以确定需要配置哪些策略。 在这种情况下,该策略集包含一个WS-Security策略,这就是为什么将此策略包含在“ 添加”下拉菜单中的原因。
- 由于您添加到服务提供者的WS-Security策略集包括
UsernameToken
作为请求者的必需令牌,因此您需要通过以下操作在绑定中为此策略指定“方式”:- 通过单击身份验证和保护,显示ServerUNTBinding的详细信息。
- 导航到身份验证令牌部分,然后单击request:MyUsernameToken 。 您应该看到如图11所示的屏幕。
图11. UsernameToken身份
- 保留此方案的默认值,然后单击确定 。
- 现在,您已指定要根据服务安全性规范将要在SOAP头中传递的UsernameToken用作服务提供者的认证令牌。 但是,请记住,WS-Security规范允许在请求消息中传递多个令牌,因此现在您需要向WebSphere指定在创建WebSphere凭证时将使用这些令牌中的哪一个(换句话说, JEE主题),以便可以将特定令牌的标识用于JEE安全,例如基于角色的授权检查。 在WebSphere中,这是通过如下配置调用方来完成的:
消费安全服务
确保服务使用者遵守服务提供者策略的最简单方法就是使用相同的策略集。 您可以通过从Application Server管理控制台中导出服务提供者策略集,然后将其导入Application Developer中来实现。
要导出策略集,请执行以下操作:
- 在管理控制台中,选择服务=>策略集=>应用程序策略集 。
- 检查My UNT策略集,然后单击Export =>,如图13所示。
图13.导出策略集
- 单击MyUNT.zip并将文件保存在本地驱动器上的某个位置; 例如,c:\ temp。
- 单击确定保存文件。
要将策略集导入到Application Developer中,请执行以下操作:
- 从Application Developer主菜单中,选择File => Import => Web services => WebSphere Policy Sets ,然后单击Next 。
- 单击浏览,然后选择上面导出的MyUNT.zip文件。 该向导将读取该zip文件并显示其中包含的策略集,如图14所示。
图14.导入策略集
- 确保选中MyUNT ,然后单击“ 完成” 。
现在,您已将策略集导入到Application Developer中,您需要创建一个服务使用者客户端,以将策略集附加到:
- 在Application Developer中,选择File => New => Other => Java => Java Project创建一个新的Java项目来容纳使用者。
- 将
HelloWorldConsumer
指定为Client项目名称 ,然后单击Finish 。 如果系统提示您更改为Java透视图,请单击“ 否” 。 - 现在选择服务提供者,Application Developer将从该服务提供者生成客户端代理,然后选择Generate => Client ,如图15所示。
图15.生成JAX-WS客户端代理
- 在Web Service Client向导中,确保选择了IBM WebSphere JAX-WS,然后单击Client project : 。
- 将
HelloWorldConsumer
指定为Client项目名称 ,然后选择HelloWorldConsumer作为客户端项目,然后单击OK 。 - 接受默认值,然后单击完成 。 Application Developer将生成JAX-WS客户端代理类和支持类。
- 右键单击生成的HelloWorldConsumer项目,然后选择New => Class 。
- 指定
com.ibm.dwexample
作为包名称,并指定ClientTest
作为Java类名称,然后单击Finish 。 - 用清单2中的代码替换生成的客户机代码,然后保存文件。
清单2. ClientTest.java
package com.ibm.dwexample; import com.ibm.dwexample.HelloWorldProvider; import com.ibm.dwexample.HelloWorldProviderService; public class ClientTest { public static void main(String[] args) { HelloWorldProviderService srv = new HelloWorldProviderService(); HelloWorldProvider port = srv.getHelloWorldProviderPort(); String resp = port.sayHello("World"); System.out.println("[response] " + resp); } }
现在,您已经创建了JAX-WS使用者,您需要将导入的策略集附加到使用者,然后生成客户端策略集绑定。 为此,请完成以下步骤:
- 导航到HelloWorldConsumer项目,然后选择Services => Clients => {http://dwexample.ibm.com/}HelloWorldProviderService => Manage Policy Set Attachment ,如图16所示。
图16.管理策略集附件
- 单击下一步 ,然后单击添加 。
- 验证服务名称是否设置为{http://dwexample.ibm.com/}HelloWorldProviderService ,然后选择Policy Set => MyUNT 。
- 输入
ClientUNTBinding
作为Binding name ,然后单击OK ,如图17所示。图17.将策略集附加到使用者
现在,您已经附加了在Application Server中创建的策略集,并将其附加到JAX-WS使用者。 您还为客户端绑定( ClientUNTBinding
)分配了名称。 最后一步是配置绑定:
- 在绑定配置中选择WSSecurity策略类型,然后单击Configure 。
- 选择com.ibm.websphere.wssecurity.callbackhandler.UNTGUIPromptCallbackHandler作为回调处理程序,如图18所示。
图18. JAX-WS使用者绑定配置
- 单击确定 ,然后单击完成 。
现在,您已经为服务使用者分配了一个策略集和一个对应的策略集绑定。 现在,您可以测试代码以确保它确实有效。
运行示例应用程序
因为本文中使用的代码演示了如何使用UsernameToken(即SOAP标头中的用户名和密码)作为用于通过Application Server进行身份验证的身份验证凭据,所以您需要确保在测试之前在Application Server上启用了安全性。 为此,请从Application Server管理控制台中,确保同时选中了“ 启用管理安全性”和“ 启用应用程序安全性” 。 如果未启用安全性,则需要重新启动Application Server才能使安全性更改生效。
要测试该应用程序,请执行以下操作:
- 在Application Developer中,右键单击ClientTest.java并选择Run As => Run Configurations 。
- 如图19所示,由于使用者需要使用Java身份验证和授权服务(JAAS)来传递用户名凭据,因此请为VM参数指定以下内容以指向JAAS登录配置文件:
-Djava.security.auth.login.config=”C:\Program Files\IBM\SDP\runtimes\base_v7\profiles\was70profile1\properties \wsjaas_client.conf”
图19.为ClientTest设置JAAS参数
- 点击运行 。 您应该看到如图20所示的客户端结果和如图21所示的服务器端结果。
图20. JAX-WS使用者结果
图21. JAX-WS提供程序结果
摘要
除身份验证,完整性和机密性外,许多Web服务还需要授权。 在本文中,您学习了如何配置WebSphere Application Server V7以选择作为SOAP标头的一部分的安全性令牌作为JEE安全性主体。 由于此配置是在策略集的绑定级别完成的,因此,如果需要,每个Web服务端口都可以具有不同的配置,或者可以像本文中那样在服务级别指定配置。 设置此配置后,开发人员即可使用JEE授权API,以便可以做出授权决策。 对于基于EJB的Web服务,可以使用注释或部署描述符将配置的JEE主体用于基于JEE角色的授权检查。
致谢
作者要感谢Bill Dodd对本文的详尽评论。
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/1001_chung/1001_chung.html