SOAP应用模式: 基础与安全

2002 年 8 月 01 日

SOAP应用模式是一个由四篇文章组成的系列,主要讨论的是如何将SOAP应用到各种各样的应用环境中去。本文是系列的第一篇,从大多数应用的基本消息交换模式:请求/响应模式出发,探讨如何通过消息加密的方式,实现安全消息传输。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

请求/响应模式

在电子商务应用中,通讯的双方常常通过交换商务文档来进行电子商务。发送方会将一个或多个文档包装在一个请求消息中,然后发送给接受方。接收方将会处理该消息的内容然后响应发送方。发送方文档的一些例子可能包括订单请求,或是制造信息,又或是病人的保健记录等。而接受方的响应的一些例子可能包括订单确认、更改控制信息以及合同确认等。

请求/响应模式需要"请求/响应"消息特性来实现。当一些商业应用被调用后,一个包含一些商业文档的请求将从SOAP发送者发向 SOAP接收者。而位于SOAP接收者端的商业应用将处理这个请求并生成响应,这个响应将被回送给发出该请求的SOAP发送者。下面我们将描述两个可互相替换的解决方案,这两个解决方案都将依赖底层传输协议的特性。无论是那个解决方案,SOAP发送者都被告知了请求消息传输的状态(成功或失败)。

Figure 1. 使用底层传输的请求/响应模式
SOAP应用模式: 基础与安全

如果底层传输协议直接支持请求及其响应的关联性(即底层协议支持请求/相应机制),那么具体的实现机制如图1所示。同步HTTP POST是这样一个底层传输协议的例子。这样一种实现机制将使用某种SOAP绑定,例如SOAP HTTP绑定。由SOAP发送者发送的作为请求的商业文档将被插入到请求消息中,成为请求消息的有效负载(消息体)。而当接收到该请求后,处理应用将产生一个将作为响应消息的有效负载并将被返回的文档,同时在响应消息中会包含合适的状态码。无论因为何种原因,如果请求消息没有被接收到,或者没有被期望的商业应用所处理,那么同样,合适的状态消息也将被底层传输层所生成并报告给SOAP发送者。

Figure 2. 使用SOAP Header的请求/响应模式
SOAP应用模式: 基础与安全

如果底层传输协议不支持请求/响应模型,那么按照如图2所示的机制将是一个合适的解决方案。这种底层传输协议的一个例子是单向的队列中间件。在这种情况下,消息标识和消息关联是通过SOAP Header来提供的。在生成请求SOAP消息时,消息标识处理器需要生成一个唯一的消息标识,并将它插入到一个SOAP Header中。这个消息标识作为SOAP请求消息的一个组成部分由SOAP应用A发送,并被SOAP应用B接收。请求消息被商业应用处理,同时该商业应用装配了响应消息。响应消息中同样包含了一个特别的SOAP Header,这个SOAP Header是由消息关联性处理器生成的,它负责将响应消息与其相关的请求消息设置连接语义。

下面的代码是该模式下的一组请求/响应SOAP消息示例:

<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
   <env:Header>
     <n:MsgHeader xmlns:n="http://example.org/requestresponse">
       <n:MessageId>uuid:09233523-345b-4351-b623-5dsf35sgs5d6
         </n:MessageId>
     </n:MsgHeader>
   </env:Header>
   <env:Body>
     ……………
   </env:Body>
 </env:Envelope>




<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
   <env:Header>
     <n:MsgHeader xmlns:n="http://example.org/requestresponse">
       <n:MessageId>uuid:09233523-567b-2891-b623-9dke28yod7m9
         </n:MessageId>
       <n:ResponseTo>uuid:09233523-345b-4351-b623-5dsf35sgs5d6
         </n:ResponseTo>
     </n:MsgHeader>
   </env:Header>
   <env:Body>
     ……………
   </env:Body>
 </env:Envelope>



SOAP应用模式: 基础与安全
SOAP应用模式: 基础与安全
SOAP应用模式: 基础与安全
SOAP应用模式: 基础与安全
回页首



使用加密机制

当我们对消息传输的安全性有所要求的时候,最直接的方法就是使用加密机制的请求模式。在使用加密机制的请求模式下,发送者期望与接收者按照彼此达成一致的加密机制来交换数据,也就是说他们使用同样的加密解密算法。需要发送的数据由初始发送者应用加密并通过SOAP被发送给接收者。当数据原封不动地到达接收应用时,接收者按照预先达成一致的解密算法进行解密。

在这个模式下,两个应用程序希望以SOAP消息中非透明的消息体的形式来交换加密后的数据,也就是说在SOAP消息这层,数据已经是密文的,对于SOAP层而言,其并不知道数据是明文还是密文,加密解密的操作完全在SOAP层之上完成。该模式对于SOAP消息层没有额外的需求。

下面是一个待加密的纯文本SOAP消息:

<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
   <env:Body>
     <m:GetLastTradePrice xmln:m="some-URI">
       <m:symbol>IBM</m:symbol>
     </m:GetLastTradePrice>
   </env:Body>
 </env:Envelope>


下面则是这个纯文本SOAP消息的加密后的版本。Body条目<m:GetLastTradePrice>被对称加密方法加密了,对称**是由键名"Symmetric Key"所标识的,同时这个Body条目加密后将以<xenc:EncryptedData>元素的形式出现,这个加密后的元素带有一个 id:"encrypted-body-entry"。为了传送这一加密数据,<SOAP-SEC:Encryption> SOAP Header条目被添加到SOAP Header中。需要注意的是,SOAP Header条目中的<SOAP-SEC:EncryptedDataList>元素包含了一个对<xenc:EncryptedData>元素的引用。而被用于加密的对称**被保存在SOAP Header条目中的<xenc:EncryptedKey>元素内,出现的形式是加密后的密文**形式,也就是说,这个**是使用RSA公钥加密的(这是一个常用的加密模型,文档数据使用诸如DES的对称加密算法加密,而加密的对称**则使用非对称的RSA加密算法加密)。

<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header>
    <SOAP-SEC:Encryption
        xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12"
        SOAP-ENV:actor="some-URI"
        SOAP-ENV:mustUnderstand="1">
      <SOAP-SEC:EncryptedDataList>
        <SOAP-SEC:EncryptedDataReference URI="#encrypted-body-entry"/>
      </SOAP-SEC:EncryptedDataList>
      <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
           Id="EK"
           CarriedKeyName="Symmetric Key"
           Recipient="John Smith">
        <xenc:EncryptionMethod
             Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
        <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
          <ds:KeyName>John Smith's RSA Key</ds:KeyName>
        </ds:KeyInfo>
        <xenc:CipherData>
          <xenc:CipherValue>加密后的对称**数据......</xenc:CipherValue>
        </xenc:CipherData>
        <xenc:ReferenceList> 
          <xenc:DataReference URI="#encrypted-body-entry"/>
        </xenc:ReferenceList>
      </xenc:EncryptedKey>
    </SOAP-SEC:Encryption>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
           Id="encrypted-body-entry"
           Type="http://www.w3.org/2001/04/xmlenc#Element">
      <xenc:EncryptionMethod
           Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">  
        <ds:RetrievalMethod
              URI="#EK"
              Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey"/>
        <ds:KeyName>Symmetric Key</ds:KeyName>
      </ds:KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>加密后的SOAP Body条目......</xenc:CipherValue>
      </xenc:CipherData>
    </xenc:EncryptedData>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>



SOAP应用模式: 基础与安全
SOAP应用模式: 基础与安全
SOAP应用模式: 基础与安全
SOAP应用模式: 基础与安全
回页首



选择性的消息头和消息负载加密

为了使加密处理更为灵活并具可扩展性,我们可以将加密操作挪到SOAP层之中来实现。在选择性的消息头和消息负载(消息体)加密模式下,参与消息交换的两个交易伙伴可以就加密签名以及校验各自的消息头、路由Header条目以及消息负载的方法达成一致。发送者或是源应用程序实施对消息负载的签名。然后发送消息的处理器实施对消息头的签名。在消息交换过程中,路由消息头可以被添加到SOAP消息头里去。而路由消息头可以被一个消息服务处理器实施签名。

Figure 3. 选择性的消息头和消息负载加密
SOAP应用模式: 基础与安全

在使用加密机制的请求模式中,两个应用程序通过加密的消息负载进行通讯。这些被加密后的消息负载将使得SOAP处理层无法对其进行处理。而在这个模式下,对消息头或者消息负载进行签名和/或加密则是SOAP处理层的责任。在图3 中,我们展示了加密约定是如何作用位于SOAP发送者的消息签名处理器以及相应的位于SOAP接收者的消息校验处理器的。而一个额外的消息路由SOAP Header条目也可以是SOAP消息的一部分,如果应消息交换的安全性的需要,这个SOAP Header条目也可以被签名和校验。

关于消息示例,大家则可以参考前面的例子自行给出。



参考资料


原文:http://www.ibm.com/developerworks/cn/xml/x-soapapp/part1/