在本教程中,您将学习如何在跨平台和跨语言的 Web 服务之间创建安全的通信。本教程将展示这样的一个场景,一个 .Net 客户端使用 XML 加密技术来访问一个 Java 语言编写的 Web 服务。
预备知识
本教程将基于 Microsoft 的 Windows 2000 及 Windows XP 操作系统。您应该对安全证书及加密技术有一个基本的了解。关于如何使用加密技术的简单介绍,您可以在加密技术:简单介绍 找到。您还应该熟悉使用 IBM WebSphere Application Server,例如,您应该知道如何启动和关闭它的全局安全。
系统需求
浏览器:Netscape 4.x 或更高版本, 或者 Internet Explorer 4.x 或更高版本 ,支持 JavaScript 。
本教程所讲解的内容是什么?
本教程讲解的是如何在一个跨平台的环境中创建安全加密的通信。它首先介绍了如何为 Web 服务应用程序创建 XML 加密的方法,然后介绍如何创建一个安全的客户端程序,该客户端将使用相同的加密设置和连接 Web 服务的安全证书。该应用场景可以在各种开放标准的平台下实现。参考资料部分显示了其他关于在不同平台之间创建安全通信的教程。不过,如果您是一个 .Net 用户,将可能不得不使用本教程的示例中描述的方法。它显示了一个 .Net 客户端连接到另外一个运行在 IBM(R) WebSphere(R) Application Server 上的 Web 服务的一个通用场景。它不仅展示了不同应用平台之间相互交互(通过 Web 服务),而且也展示了不同编程语言之间的交互。
在本教程中,我们将:
使用 WebSphere Studio Application Developer 创建一个简单的在线书店 Web 服务应用程序,我们首先会从一个 Web 服务描述语言(Web Services Description Language,WSDL)文档开始。
配置该 Web 服务的 XML 安全。
编写一个 Visual Basic .NET 客户端程序来访问该 Web 服务,并且配置它使用相同的 XML 加密设置和 Web 服务使用的相同安全证书。
测试这个 .NET 客户端。
简单地了解一下在协同使用 .Net 时存在哪些互操作性方面的缺陷。
我应该如何学些本教程?
本教程主要展示了如何让一个用 Visual Basic 编写的 .Net 客户端程序连接到一个用 Java 语言编写的 Web 服务,这里假设您不得不使用 .Net 客户端平台。您应该对 Web 服务及其相关技术(例如,Web 服务描述语言(Web Services Description Language,WSDL)、简单对象访问协议(Simple Object Access Protocol,SOAP))有一个基本的了解,并且知道哪些人需要学习如何构造一个 Java 语言编写的 Web 服务和一个用 icrosoft Visual Basic .NET 编写的客户端程序,而且它们之间是通过 XML 安全技术来彼此通信的。本教程是对我早期的一个关于基本身份验证和 XML 数字签名的教程的补充。(请参看参考资料中的链接。)
本教程中我用来创建和运行 Web 服务的开发工具包括:
IBM WebSphere Studio Application Developer 5.1.0
Microsoft Visual Studio .NET 2003 with Web Services Enhancements 1.0 SP1.
本教程将基于 Microsoft 的 Windows 2000 及 Windows XP 操作系统。您应该对安全证书及加密技术有一个基本的了解。您还应该熟悉使用 IBM WebSphere Application Server,例如,您应该知道如何启动和关闭它的全局安全。如果您想阅读本教程,但又不能确定自己是否懂这些主题,您可以参看参考资料中一些相关文档的链接。
样本代码
在开始学习本教程之前,请解压缩本教程所提供的源代码包 ws-encryptcode.zip。在源代码文件夹里面有两个子目录,每一个都包含两个文件。
Enc_wsdl_and_Java_implementation_file 目录包括:
bookstoreEnc.wsdl —— 这是一个 WSDL 文件,您将在教程的开始使用它来创建 Web 服务框架,请参看 检查 WSDL。它定义了您的 Web 服务将要提供的信用卡购买服务。
CreditCardBindingImpl.java —— 一个 Java 源代码文件,您将在 创建 Web 服务 完全地实现信用卡购买服务。
Enc_cert_and_keystore 目录包括:
interops-enc-receiver.jceks
interops-enc.cer
interops-enc-receiver.jceks 密钥库文件包含了私钥,您的 Web 服务将使用该密钥来解密接受到的信息。您将在 安全证书 配置这个 Java Web 服务来使用它。interops-enc.cer 是一个 X.509 证书,它包含了一个公钥,.Net 客户端将使用该密钥来加密它的输出消息。您将在 安装公钥安全证书 中配置客户端来使用它。
关于作者
对于与本教程的内容有关的技术问题,请您通过 proctor@uk.ibm.com 与作者 Hedley Proctor 联系。
Hedley Proctor 是一名软件工程师,工作在位于英国的 IBM Hursley 实验室。他从事 WebSphere SDK for Web Services 的版本 5 和 5.1 的研究,专攻 Eclipse 插件、样本和互操作性。他在牛津大学获得物理学士学位,并且在杜伦大学哲学研究生学位。
加密技术:简单介绍
在我们真正开始之前,先简单介绍一下加密技术是如何工作的。最早期的计算机加密技术仅使用一个对称的,或者是安全的密钥。所有想加密和解密的参与方都必须能访问到这个相同的密钥。一个叫做 DES(后来有了加强的三重 DES)的加密算法成了这种对称加密的标准。然而,这个加密系统有一个非常大的弱点,那就是密钥必须分发给所有的参与方。如果密钥被截取了,敌对方就能解密所有的信息。
在 1970 年, 加密算法获得了一个巨大的突破,那就是公用及私有密钥加密机制的发明。该加密机制使用了一个叫做 陷门(trapdoor)函数的数学函数类。这种算法使用了两个密钥:一个用来加密数据,另外一个用来解密数据。如果我希望别人能发给我加密数据,我只需要简单地把公钥分发给他们。然后他们使用这个密钥来加密信息,并且我使用私有密钥对这些加密信息进行解密,这种算法能保证安全的关键就是因为只有我拥有私钥。现在出现了很多基于这种机制的加密算法,但是到目前为止最常用的还是 RSA。
公私钥加密比对称加密要安全得多,因为它不需要进行密钥分发。但是使用大多数非对称加密算法对数据进行加密的速度都是非常慢,慢得要加密大量数据通常是不可能的。为了能在实际应用中得到最好的使用,一个混合系统被开发出来了:
发送者首先生成一个对称会话密钥,并且用这个密钥来加密真正得数据。
发送者使用接受者得公钥对会话密钥进行加密,并且把这个加密了得密钥随消息发送给接受者。
接受者使用他或她得私钥对这个会话密钥进行解密,然后使用这个会话密钥对消息数据进行解密。
这样的话,我们就既有了对称加密得速度,又有了公钥加密的安全。如它名称所示,会话密钥仅使用一次。所以,即使敌方组织使用何种方法解密了会话密钥,他们也仅仅能解密一个消息。这个方法也是我们在本教程中要用到的,并且使用三重 DES 作为我们的对称加密算法,RSA 作为我们的非对称加密算法。
创建java web服务
介绍
在这个部分,我们将使用 IBM 的 WebSphere Studio Application Developer 创建一个简单的在线书店 Web 服务应用程序,并且首先从一个 WSDL 文件开始。
检查 WSDL
启动 WebSphere Application Developer
单击 File > New > Dynamic Web Project 菜单。输入 bookstoreEnc 作为您的新项目名。
展开项目目录,右击 WebContent 目录,并且从弹出菜单中选择 Import。然后在对话窗的列表框中选择 File System。定位到包含 bookstoreEnc.wsdl 和 CreditCardBindingImpl.java 文件的目录中,把它们导入到 WEB-INF 文件夹中。事实上,您把它们导入到哪一个文件夹本身是没有关系的,因为当您创建 Web 服务时,WebSphere Studio Application Developer 会把它们移动到正确的位置。
打开 WSDL 文件,它是以文字绑定样式的文档格式编写的。在我以前的教程中,我使用过了一个在线书店的示例。那个教程中的 WSDL 文件定义了一个叫做 OrderBook 的 Web 服务,用户通过传入他或她想购买的图书的标题来调用这个 Web 服务。我展示了用户是如何对这个消息进行数字签名,以便书商能知道这个消息是由谁发生来的。
对于订单的下一个阶段,客户可能想发送信用卡号。很明显,在 Internet 上以一种可读的形式来发生这种号码非常不安全,所有它必须加密。bookstoreEnc.wsdl 定义了一个叫做 CreditCardPurchaseService 的 Web 服务。在一个真实的环境中,一旦信用卡信息被解密了,它将被传入到一个帐务系统。但是在本教程中,由于这仅仅是一个样本,所以我们仅编写了一个叫做 CreditCardBindingImpl.java 的样本实现,该实现仅执行了一个基本的数据验证。如果您阅读了这个 Java 文件,您会发现它仅验证输入的号码至少有 12 个数字。如果有 12 个数字,Web 服务发送回一个消息确认数据已经被正确接受,如果没有达到 12 个数字,Web 服务发送一个响应信息表示数据需要重发。
注意,响应消息没有包含任何机密信息,所以它可以不需要加密就发送。使用对消息任何一种加密都将增加发送方创建消息及接受方处理消息的时间,从而影响整个服务的性能,所以我们应该尽量在必要时才使用加密。
创建 Web 服务
单击 File > New > Other > Web Services > Web Service 菜单项来启动 Web 服务向导。
在 Web Services 页上面,选择 Skeleton Java bean Web Service 作为 Web 服务类型。单击 Next 按钮。
在 Service Deployment Configuration 页上,选择您在前面创建的动态 Web 项目作为 Service Web Project。您将需要选择一个服务器,我这里使用 WebSphere Application Server 5.0.2 Test 服务器,但是您可能希望使用一个非测试服务器。
在 Web Service Selection 页上,找到并选择 bookstoreEnc.wsdl 文件。然后单击 Next 按钮。
在 Web Service Skeleton Java Bean Configuration 页上,有两个样本安全配置可以选择 —— XML Digital Signature 和 XML Encryption。不过,如果您选择一个空白的配置并且完全手工配置这些选项,您将更好地理解整个过程,所以选择缺省的没有安全,然后单击 Next 按钮。
在 Web Service Publication 页上,把发布选项都保留为选中。然后单击 Finish 按钮。
如果您展开了您的 Web 服务项目的 JavaSource 文件夹, 您将看到一组 Java 文件被 WebSphere Studio Application Developer 自动创建了。WSDL 文档是一个 Web 服务的简单定义。WebSphere Studio Application Developer 已经创建了允许消息传入及传出这个 Web 服务的代码。不过它不能为您编写任何业务逻辑代码,因为只有您才真正知道如何处理这些消息。在 JavaSource 目录中,有一个叫做 CreditCardBindingImpl.java 的 Java 文件包含了 Web 服务的业务逻辑,这个 Java 文件名的意思是 credit card binding implementation(信用卡绑定实现)。这个文件的名称与我们样本代码中的实现文件相同,虽然它不是相同的文件。 如果您打开它,您会发现它包含一个空的方法定义,这也是为什么我们经常叫这个文件为 骨架实现文件。您将需要使用 真正的实现文件来替换它,也就说,使用我们的样本代码归档文件中同名的文件。
把您从 ws-encryptcode.zip 文件中提取的 CreditCardBindingImpl.java 文件导入到 JavaSource 目录,以便它会重新覆盖骨架文件。这将在控制台产生一个错误,您应该确认这个修改已经反映到了服务器。不过,您有许多修改要做,而且这些修改都要反映到服务器,所以只有在完成 webservices.xml 设置 之后才能让服务器使用这个新的文件。
建立 TCP 监视器
我们现在可以运行这个 Web 服务了,就像我们现在拥有它一样。不过,在真正调用 Web 服务之前检查一下要发送的 SOAP 消息是非常有帮助的,所以先建立一个 TCP 监视器服务器。这个监视器将在一个端口接受 SOAP 消息,然后从另外一个端口发送出去。
选择 Servers 视图。
单击鼠标右键并从弹出菜单中选择 New > Server and Server Configuration。
选择服务器类型为 Other > TCP/IP Monitoring Server,并且指定一个服务器名称,然后单击 Finish 按钮。
配置 Web 服务使用 XML 加密
介绍
在这个部分,我们将配置我们的 Java Web 服务使用 XML 加密。
安全证书
我们实际上需要的唯一安全证书就是公用和私有密钥,因为会话密钥将会由客户端生成。记住,加密密钥一定不能保存再 JKS 格式的密钥库文件里,因为这种格式的安全性不够。如果一个攻击者能盗取您的密钥,使用好的加密技术将没有任何意义!服务器用来解密消息的私有密钥应该保存在 JCEKS 格式的文件里。我已经在 ws-encryptcode.zip 中提供了公用和私有的密钥证书:
interops-enc.cer 是一个为客户端使用的 X.509 格式的公钥证书。
interops-enc-receiver.jceks 是一个 JCEKS 格式的密钥库文件,保存了服务器使用的公用及私有密钥对。
这些是 1024 位的 RSA 密钥。
当试图创建一个可互操作的及加密的 Web 服务时,有一个非常重要的要点必须牢记于心。当一个加密了的 SOAP 消息发送出去后,这个消息会包含一个 标记。这个标记告诉了消息的接受者,他或她的哪一个私钥将被用来解密这个信息,因为他或她可能有不止一个私钥。生成 标记的缺省算法使用的是 X.509 公钥证书的 Subject Key Identifier 扩展。不过,如果您是使用 Java 密钥工具来生成证书,它们将生成 X.509 V1 证书,而且这个版本的证书没有扩展部分,因为只有到了 X.509 V3 标准后才出现了这个扩展。当 Subject Key Identifier 扩展不存在时,用来生成 标记的方法没有在当前的 Web 服务标准中很好地定义了,您可能会发现不同厂商实现了不同的算法。为此,最好总是使用 X.509 V3 公钥证书,它可以被导入,而不是由 Java 密钥工具生成的。大多数认证中心(Certification Authorities,CAs)都将发布 X.509 V3 证书。
把 interops-enc-receiver.jceks 密钥库文件保存到您选择的位置。我们在下一部分将告诉服务器在哪里来找到这个文件。
webservices.xml 设置
所有的安全设置都是用 webservices.xml 文件来进行配置的:
展开 bookstoreEnc > WebContent > WEB-INF 文件夹,并且打开 webservices.xml 文件。 这就生成很多页面,并由底部的 tabs 来区分。选择 Security Extensions 页。
在这个页面的右边,我们可以看到两组配置设置: Request Receiver Service Configuration Details 及 Response Sender Service Configuration Details。请求接受者设置决定了服务器如何处理接受到的消息,而响应发送者设置指定了被发送回的消息的格式。
我们想服务器要求接受到的消息被加密。展开 Request Receiver Service Configuration Details > Required Confidentiality 并且单击 Add 按钮。对于那些需要加密的消息,您可以看到它的各个部分都有两个选项:body 或用户名符号。 选择 bodycontent 并单击 OK 按钮。
检查这个页面上的其他设置中的一个是非常值得的。在页面的左侧,展开 Server Service Configuration,您应该看到它有一个参数为 ActorURI,并且没有任何值赋给了这个参数。如果有一个值,则表示发送给这个 Web 服务或从它发送出的消息通过了一个中介。事实上,如果我们使用了 Web 服务向导来创建一个安全的 Web 服务,一个作为中介体的角色将被使用。 然而,.NET 服务缺省没有使用这样的一个角色。所以,如果您想创建一个需要与 .Net 进行交互的 Web 服务,请确保您已经设置了 ActorURI 值为 null。
选择 webservices.xml 文件的 Binding Configurations 页。
在该页的右手边有两个部分:Request Receiver Binding Configuration Details 和 Response Sender Binding Configuration Details。展开 Request Receiver Binding Configuration Details > Encryption Information 并单击 Add 按钮。
当 Web 服务接受到一个加密了的 Web 服务后,它会阅读消息的头信息,这个可以告诉它使用了哪一种加密算法来这些消息。您需要使用这个对话框来告诉 Web 服务到哪里寻找它可能遇到的算法组合的密钥。我们想使用 3 重 DES 作为对称加密算法来加密数据,而 RSA 作为非对称加密算法来加密对称加密会话密钥,所以输入以下信息:
加密名称: InteropsEnc
数据加密算法: http://www.w3.org/2001/04/xmlenc#tripledes-cbc
密钥加密方法算法: http://www.w3.org/2001/04/xmlenc#rsa-1_5
加密密钥名称: 保留空白
加密密钥定位器: InteropsEncKeyLocator
然后单击 OK 按钮。
现在我们需要定义密钥定位器,移动到 Key Locators 部分,并且单击 Add 按钮。在对话框中,输入以下信息:
密钥定位器名称: InteropsEncKeyLocator
密钥定位器实现类: com.ibm.wsspi.wssecurity.config.KeyStoreKeyLocator (default)
密钥库 storepass: interops
密钥库路径: c:\keystores\interops-enc-receiver.jceks
密钥库类型: JCEKS
继续在密钥定位器对话框中,单击密钥 Add 按钮,并输入以下信息:
别名: interops-private-key
密钥通行证: interops
密钥名称: CN=Interops Encryption
单击 OK 按钮来关闭这个对话框。
这是 Encryption Information 和 Key Locators 之间需要注意到的两个部分:Trust Anchor 和 Collection Certificate Store。通常,用来解密的私钥是一个证书链的一部分,这个证书链的末尾一般是一个可信的根认证中心(CA)。为了让服务器能够信任私钥,您必须把中间证书的位置放到 Collection Certificate Store 列表中,已经把根认证中心(CA)证书的位置放到 Trust Anchor 列表中。不过,我在该教程中提供的虚构证书不是一个证书链的一部分,所有我们不必使用这部分中的任何一个。
到此请保存 webservices.xml 文件。您现在对 XML 加密有了正确的设置了,所以您可以在服务器上重启该项目。记住我们正在使用安全,所以我们不能保证安全是否在服务器上面启动了。如果没有启动,双击服务器配置,并且修改 Security 页上的设置。鼠标右键单击服务器,然后从弹出菜单中选择 Restart project > DefaultEAR。
创建 .NET 客户端程序
介绍
在这个部分,我们将编写一个 Visual Basic .NET 客户端来访问我们的 Java Web 服务。我们将配置客户端使用根 Web 服务相同的 XML 加密设置和安全证书,并且将测试这个客户端,以确定一切工作正确。
安装公钥安全证书
设置引用
现在相应的安全证书已经安装完成,您可以开始编写客户端程序了。
开启 Visual Studio .NET。
创建一个新的 Visual Basic .NET 项目。选择 Windows Application 类型,输入项目名为 SecureInteropsEnc。 这将创建一个空白窗口表单。
展开项目并右击 References,从弹出菜单中选择 Add Reference。
滚动 .Net 引用列表,并且选中 Microsoft.Web.Services.dll。单击 Select 按钮,然后单击 OK 按钮。您应该可以看到引用已经添加到了您的项目中。
再次右击 References 并且从弹出菜单选择 Add Web Reference。
假设您的 Web 服务与您的客户端运行在同一台机器上,那么 WSDL 文件的位置应该是 http://localhost:9080/bookstoreEnc/wsdl/com/ onlinebookstore/www/bookstoreEnc.wsdl,因为 bookstoreEnc 是您前面创建的动态 Web 项目的名称,而 www.onlinebookstore.com 是 WSDL 文件的命名空间。如果您的 Web 服务运行在远程机器上,您可以使用正确的主机名或者 IP 地址来替换上面 URL 中的 localhost。在输入框中输入相应的 URL,并单击 Return 按钮。
在上图中您可以看到我的 Web 服务正在一个名为 hproctor 的主机上运行。
一旦您输入了 URL,您就应该得到 CreditCardPurchaseService 的描述信息,它有一个名为 creditCardPurchase() 的方法。修改对 bookstoreEnc 的引用名称,并且单击 Add Reference 按钮。这会在您的项目中产生大量的代码存根(stubs),您可以在类视图中看到这些存根。扩展类视图,直到您看到了 CreditCardPurchaseService 类,并且双击它以便能在编辑器中打开它。
我们需要修改这个类,让它使用 Web Services Enhancements 代码,而不是更老的 Web 服务代码。这个类继承于 Microsoft.Web.Services.WebServicesClientProtocol,而不是继承于 System.Web.Services.Protocols.SoapHttpClientProtocol。
我们也想使用 TCP 监视器来查看客户端消息,所以把端口号从 9089 更改为 9081。然后关闭 CreditCardPurchaseService 代码窗口。
为了在 Windows 下管理证书,单击 Start > Run 菜单,并且输入 mmc 并敲回车键。
通常,在主窗口里面有一个控制台窗口将被打开。如果没有,单击 File > New 菜单。
单击 Console > Add/Remove Snap-in... 菜单项。
单击 Add 按钮,并且从列表中选择 Certificates,然后单击 Add 按钮。
为您的用户帐号接受管理证书的缺省值,然后单击 Finish 按钮。
关闭 Add Standalone snap-in 对话框,并且在 Add/Remove Snap-in... 对话框上单击 OK 按钮。
展开 Certificates -- Current User 列表,您可以看到各种各样的证书库和它们包含的证书。
您应该把公钥证书添加到 Personal 和 Trusted Root Certification Authorities 库中。一般来说公钥证书只保存在 Personal 库中,但是由于这是一个自认证的证书,为了让 .Net 能够信任它,它也应该安装到 Trusted Root Certification Authorities 库中。双击 interops-enc.cer 文件。
单击 Install Certificate... 按钮,这将打开 Certificate Import 向导。单击 Next 按钮。
选择 Place all certificates in the following store 并且单击 Browse按钮。
选择 Personal 库并且单击 OK 按钮。
向导将显示您已经选择了 Personal 库,单击 Next 按钮,然后单击 Finish 按钮。
重复这些步骤把该证书添加到 Trusted Root Certificate Authorities 库。当然您可以添加一个证书到任意多个证书库里。
创建表单
在这个表单上,我们将需要一个文本框来输入信用卡号,一个命令按钮来调用 Web 服务,以及一个文本框来显示响应消息。另外一个用来清除这两个文本框的命令按钮也是非常有用的,这样我们就可以尝试不同的输入,所以我们将添加两个文本框和两个命令按钮到表单上。
将第一个文本框的名称更改为 Input,并且把它的 text 属性设置为空字符串。
将第一个命令按钮的名称更改为 InvokeWebService,并且设置它的文本显示为 Invoke Web Service。
将第二个文本框的名称更改 WebServiceResponse, 并且也把它的 text 属性设置为空字符串。
将第二个命令按钮的名称更改为 ClearTextBox,并且设置它的文本显示为 Clear Text Boxes。
您的表单最后应该看上去如下图所示:
编写代码
右击表单,并从弹出菜单中选择 View Code。当编写客户端代码时,您将使用在您在 设置引用 中添加的引用链接 —— Web Services Enhancements DLL 中的类。 您将需要在代码的最开头使用导入声明,以便将下面的声明添加到类定义中:
Imports Microsoft.Web.Services
Imports Microsoft.Web.Services.Security
Imports Microsoft.Web.Services.Security.X509
下一步,您需要添加代码来调用 Web 服务,这些代码在用户单击 Invoke Web Service 按钮时被执行。从代码窗顶部的两个下拉列表框中分别选择 InvokeWebService 作为对象,以及 Click 作为方法。当有人单击这个按钮时,您第一件要做的事情就是创建一个对象来代表 Web 服务,所以添加以下代码:
Dim WebService As New bookstoreEnc.CreditCardPurchaseService
在消息被发送之前,您想对它进行加密。但是在对它进行加密之前,您需要有正确的公钥。您已经把公钥存储在了 Personal 证书库中,所以您可以打开那个证书库,并且搜索这个公钥,直到找到它的位置为止。证书的 X.509 名称是 Interops Encryption,所以您可以搜索所有证书直到您找到一个匹配的为止。添加如下代码:
Dim encryptionCertificate As X509Certificate
Dim store As X509CertificateStore
store = X509CertificateStore.CurrentUserStore(X509CertificateStore.MyStore)
store.OpenRead()
For Each cert As X509Certificate In store.Certificates
If (cert.GetName.IndexOf("Interops Encryption") > -1) Then
encryptionCertificate = cert
End If
Next cert
现在,您已经有了正确的公钥证书。您可以使用它来加密消息了吗?在 .Net 中,为了控制如何处理输入或输出消息,您首先需要一些对象,这些对象封装了处理数据的一种专门方法。然后,您添加那些对象到您的 SOAP 消息的各个专门部分,或者添加到如 .Net 提到的一个专门的 Web 服务的 SOAP context。使用这种方法,.Net 能理解 SOAP 消息的每一个部分应该被如何处理。例如,您首先需要从安全证书中生成一个 X509SecurityToken。 X509SecurityToken 可以被添加到 SOAP 消息,而且它可以代表证书的公钥。这就是对一个需要进行数字签名的消息要做的事情。不过在这个场景里,您不想添加 X509SecurityToken 到消息中,而是您应该使用它对数据进行加密:
Dim encryptionSecurityToken As New X509SecurityToken(encryptionCertificate)
Dim encryptedData As New EncryptedData(encryptionSecurityToken)
现在您已经定义了 encryptedData 对象。 但是它需要添加到 SOAP 上下文的哪一个部分呢?很好,对于初学者,您仅需要对输出的消息进行加密,而您从服务器接受到的消息没有被加密。因此,您需要使用对象的 RequestSoapContext() 方法来表示您的 Web 服务,从而以为着您感兴趣的是请求消息,而不是响应消息。还有,因为它属于安全,encryptedData 对象必须添加到 SOAP 上下文的 Security 部分:
WebService.RequestSoapContext.Security.Elements.Add(encryptedData)
到这个阶段,您的 SOAP 输出消息已经被正确加密了。然而,您还有一个修改要做,缺省情况下,.Net 强迫 SOAP 路径头修改被处理。而这个实例没有使用路径头,所以您可以修改头以便对它的处理变成是可选的:
WebService.RequestSoapContext.Path.MustUnderstand = False
最后,您可以添加代码来调用 Web 服务。您希望用户在 Input 文本框中输入的数据发送给这个 Web 服务,而响应消息显示在 WebServiceResponse 文本框中:
WebServiceResponse.Text = WebService.creditCardPurchase(Input.Text)
最后,您可以实现 ClearTextBox 对象的 Click 方法,用它来清空这两个文本输入框:
Input.Clear()
WebServiceResponse.Clear()
运行 .NET 客户端
为了从 Visual Studio 运行 .NET 客户端,选中项目并右击,然后从弹出菜单选择 Debug > Start New Instance。
输入一个长的数字字符串,并单击 Invoke Web Service按钮。
如果您输入 12 或超过 12 个数字,Web 服务应该响应说它接受到了信用卡号:
在 WebSphere Studio Application Developer 中,选择面板下面的 TCP/IP Monitor 页,然后双击窗口的标题栏来最大化它。SOAP 请求应该看上去类似于下面的代码(我做了一点小小的编辑,以增加可读性):
http://localhost:9081/bookstoreEnc/services/CreditCardPurchase
uuid:0b4706aa-604f-490e-9a19-828c21981288
2004-02-26T23:55:53Z
2004-02-27T00:00:53Z
X/cJNXQ2PMsP5YC3CjTZAak1534=
VGtI79mcqGFgXjIOoW3jUpolIrmL/gi0iSbvZh3fMkoipLLVrYLBoBTxO0T6hW
Gsq+TOJRfU8eHkBDheDxVdDVAq1h/jnP2I/mfKfu+H8l/MZ9v+LX6PpvprMU63
DwNZO0YGsajTCHhzrkXrokOjwjID1D6PcYpn67YDa4rRF+M=
K0WDlESZe2fxHtdllzaDWDZyu5rD/zUBNms76BQOPUsVmE5DKfwmdK6A/cKBG9ECg1j
lqqhVBVntFqdfisl/o72ospN+DT5ClkMIDz17CFNASvDpgGytVJ0PM1+PSW+y
And the response should look like this:
Card details received.
您也可以验证在您输入一个非法的信用卡号时 Web 服务会生成一个错误消息:
总结
您首先学习了如何创建一个 Java Web 服务以及配置它使用 XML 加密,然后学习了如何设置安全扩展(Security Extensions)和绑定配置(Binding Configurations)来使用三重 DES 技术加密消息体,以及如何使用 RSA 算法非对称地加密三重 DES 会话密钥。然后您配置了密钥定位器,以便 Web 服务能对这些加密密钥进行访问。
在下一步,您为 .Net 客户端安装了一个公钥证书,并创建了一个 GUI 界面。您通过添加对 Web 服务的引用来设置客户端使用您的 Web 服务。您学习了如何搜索证书库来定位正确的证书,然后使用这个证书来创建一个加密的数据对象。通过添加这些到 SOAP 请求上下文的安全部分,您告诉了 .Net 去加密输出的消息,但是没有期望未加密的消息返回。然后,您可以运行这个 .NET 客户端,并且验证它运行正确。当您输入一个有效的信用卡号时将得到一个验证消息,如果输入一个无效的信用卡号,将返回一个错误消息。
互操作性是一个非常困难的方面。首先,为了实现互操作,不同的厂商必须实现相同的标准。在本教程中的示例是基于 Web 服务安全性(WS-Security)标准的(请参看参考资料)。第二,您必须清楚,就是这些厂商都实现了相同的标准,您还必须知道它们的缺省配置。所以,对于安全协操作,您需要记住的一些关键点包括:
始终使用 X.509 V3 安全证书,它带有一个主题密钥身份(Subject Key Identifier)扩展。
知道您是否希望使用一个中介(ActorURI)。
知道两边都在使用什么算法。
决定是否想处理路径头。
觉得是否想使用一个时间戳。
如果您在协同操作的试验期就有问题,请确定您使用了一个类似于 TCP/IP 监视器的工具来可视化地监视 SOAP 消息。XML 标记可能告诉您,两个厂商可以采用了不同的方法来实现同一个标准。还有,请非常小心您的安全证书。因为 Java 密钥库文件采用的是一个不同于 PKCS 的证书格式,您需要保证客户端使用的证书正确对应于服务器使用的证书,并在把证书从一种格式转变为另外一种时没有错误。
本教程也展示了如何把 .Net 客户端带进一个开放标准的 Web 服务世界。本教程还展示了 Web 服务如何通过通用交互协议使所有平台互操作。这个同样的场景可以在其他平台和编程语言上的 Web 服务中来实现,但这是另外一个教程的主题了。
参考资料
下载 ws-encryptcode.zip 中的所有源文件。
Hedley Proctor 撰写的“保护 Web 服务:互操作性”(developerWorks,2004 年 2 月)介绍了使用基本身份验证和数字签名的互操作性。
Andy Clarke 和 Mike Edwards 撰写的“Developing a .NET client to interact with a WebSphere Web Service”(developerWorks,2003 年 10 月)并没有介绍安全性,但是却介绍了如何构造基本的互操作性演示。如果您相当不熟悉互操作性,并且感到学习本教程比较困难,Andy 和 Mike 的这篇文章就是一篇很好的入门文章。
“Secure, reliable, transacted Web services”(developerWorks,2003 年 10 月)是由来自 IBM 和 Microsoft 的 Web 服务架构师共同撰写的。这篇文章描述了保护 Web 服务互操作性的标准是如何制订的。
WebSphere Application Server Web services security documentation 详细解释了所有 webservices.xml 设置的含义以及配置它们的方式。它涵盖了身份验证、数字签名和加密及其在 Java Web 服务和客户端的应用。
要获得更多关于使用的 Microsoft .NET 的 Web 服务互操作性的信息,请阅读 Jeannine Hall Gailey 撰写的“Encrypting SOAP messages using Web Services Enhancements”(MSDN,2003 年 3 月)。
Web 服务安全性(WS-Security)1.0是 IBM、Microsoft 和 Verisign 联合制订的 Web 服务身份验证、数字签名和加密的正式规范。
Web 服务互操作性组织(Web Services Interoperabilty Organization,WS-I.org)解决了 Web 服务的不同实现之前的许多互操作性问题,它通过概要定义了如何实现像 Web 服务安全性(WS-Security)这样的规范。
WebSphere Application Server InfoCenter 解释了 WebSphere Application Server 安全性与 Java 2 Platform 定义的安全性之间的不同。
Java keytool documentation 解释了如何使用 Java keytool 来生成自签名证书或者从 JKS 或 JCEKS keystores 导入导出证书。
OpenSSL 项目是一个开放源代码倡议,它提供了实现安全套接字层(Secure Socket Layer,SSL)的工具包。它还提供了加密库。通过使用该工具包,可以用多种格式生成自签名的证书。
“Introduction to the PKCS Standards”概述了广泛使用的 PKCS 加密标准。它是由 Mohan Atreya 撰写的,Atreya 在开发 PKCS 的公司 RSA 工作。(PDF 格式的文档)
|