增强Web服务安全性的新技术

[摘要]如果没有良好的安全性,Web服务将永远不能发挥它的潜能。本文重点讨论了WS-Security及其相关的技术,它们代表了Web服务安全性的未来。本文对这些新兴的安全标准进行了概述,并对这些安全标准的作用、工作方式和协作形式进行了说明。讨论的主题包括完整性、保密性,以及如何通过公钥加密、WS-Security和其他技术来实现完整性和保密性。本文还讨论了一些关键的WS-Security组件,例如wsu命名空间。

 

    如果没有良好的安全性,Web服务就不能发挥它的作用。然而,SOAP的最初设计者却选择了推迟定义解决此问题的方法。由于Web服务开发初始希望其简单易用——但要确保其安全却不是一件简单的事情,因此,这是一个合理的选择。但是,安全问题不能永远拖延下去。因此,MicrosoftIBM以及其他公司强强联合,共同致力于解决此问题。其成果是制定了一组提供Web服务安全性的规范,其中最重要的是WS-Security。本文将对这些技术如何工作进行全面概述。

    从某个角度来看,Web服务安全性的设计者所面临的任务看起来很简单。毕竟,分布式安全已经存在有效的机制,包括Kerberos、公钥技术以及其他。因此,这些设计者所面临的任务并不是要发明新的安全机制。相反,他们的目标是定义Web服务领域(一个构建于XMLSOAP之上的领域)中现有安全机制的使用方式。目前已经有几个与安全相关的规范,包括:

l         WS-Security:其他所有规范的基础。它定义了允许传递安全令牌的SOAP扩展,安全令牌可安全地对客户端进行标识和身份验证、确保消息完整性以及提供消息保密性。Web服务安全性附录(Web Services Security Addendum)是一个附加规范,它向原始文档中添加了一些细节和修正。

l         WS-SecurityPolicy:指定如何定义明确声明Web服务优先权和要求的安全断言。

l         WS-Trust:定义如何获得安全令牌。

l         WS-SecureConversation——定义如何创建与Web服务进行特殊会话的上下文,以及如何创建用于该上下文的密钥。

l         Web Services Security Profile for XML-based Tokens:定义如何将基于XML的技术(例如,安全断言标记语言[SAML]和可扩展权限标记语言[XrML])与WS-Security一起使用。这些规范自成体系,并以此为基础构成了易于使用、可协作并且相当完善的方法,以提供Web服务安全性。

WS-Security

    WS-Security 定义了一个用于携带安全性相关数据的 SOAP 标头元素。如果使用 XML 签名,此标头可以包含由 XML 签名定义的信息,其中包括消息的签名方法、使用的密钥以及得出的签名值。同样,如果消息中的某个元素被加密,则WS-Security标头中还可以包含加密信息(例如由XML加密定义的加密信息)。WS-Security并不指定签名或加密的格式,而是指定如何在SOAP消息中嵌入由其他规范定义的安全性信息。WS-Security主要是一个用于基于XML的安全性元数据容器的规范(摘自《了解 WS-Security》,http://www.microsoft.com/china/MSDN/library/WebServices/default.mspx

    WS-Security定义了向SOAP添加安全性的基本技术。其宏伟目标是为SOAP消息提供端对端的消息级安全性(message-level security),但WS-Security规范并不十分冗长,细数起来也只有20多页。这是因为WS-Security几乎没有定义什么新技术,而是定义了一种使用SOAP的现有安全技术的方法。或许,WS-Security定义的最基本内容是位于SOAP标头中的<Security>元素。包含该元素的SOAP消息的结构如代码段1所示。

代码段1 Security 元素:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope
    xmlns:s="
http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext"
>
    <s:Header>
        <wsse:Security>
            ...
        </wsse:Security>
    </s:Header>
    <s:Body>
        ...
    </s:Body>
</s:Envelope>

    正如这个简单的架构所示,WS-Security定义了它自己的命名空间。在任何可能的位置,WS-Security的设计者都会遵守现有的这些标准和技术,而只是专注于指定如何在SOAP中使用它们。

    WS-Security描述如何实现完整性和保密性。完整性使接收方能够确保从消息中接收的数据在传输过程中没有被篡改;保密性可确保数据在传输过程中不会被窥视。它还描述了如何发送安全令牌,例如用户名/密码组合、Kerberos票据或X.509证书等。下面三部分内容描述WS-Security如何处理其中的每个领域。

发送安全令牌(Security Token

    消息接收方遇到的最基本的问题可能是:我正在和谁交谈?问题虽然简单,但答案却非想像的那么简单。在网络中表明身份的方法有多种(用户名、Kerberos票据或X.509证书等),进行身份验证的方法也有不少。例如,通过用户名以及随附的密码,可以证明用户的真实身份。相反,Kerberos票据由发行方使用票据接收方可验证其正确性的密钥进行加密。此外,还可以随证书一起发送数字签名来验证用户身份。WS-Security的设计者选择了依赖多种传输方法和身份验证方法。实际上,WS-Security根本没有定义如何进行身份验证。相反,该规范指定了如何在SOAP标头的Security元素中传输多种不同的安全令牌。令牌的接收方可以根据偏好,以任何方式使用其中包含的信息。最常见的用法可能是验证令牌发送方的身份,但也可以采用其他方式使用令牌。

    尽管WS-Security规范允许任何类型的安全令牌,但它明确地定义了三种方案。最简单的(尽管不一定总是最安全的)方案是发送包含用户名和密码的安全令牌。要实现这个目标,WS-Security定义了一个包含用户名和密码的<UsernameToken>元素。以下是仅包含<UsernameToken>Security元素的一个简单示例:

<wsse:Security
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:UsernameToken>
        <wsse:Username>Diana</wsse:Username>
        <wsse:Password>mY5ecRet</wsse:Password>
    </wsse:UsernameToken>
</wsse:Security>

    还定义了功能更强大的方案,例如发送摘要版密码。由于通过网络发送未加密的密码并不是一种非常有效的身份验证机制,因此很可能会使用UsernameToken元素来验证经由加密连接发送的SOAP消息,例如使用安全套接字层(Secure Sockets LayerSSL)发送的消息等。

    WS-Security定义的第二个方案是发送包含Kerberos票据的安全令牌。像所有的安全令牌一样,在SOAP标头中发送的Kerberos票据是Security元素的一部分。下面是一个示例:

<wsse:Security
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:BinarySecurityToken
        ValueType="wsse:Kerberosv5ST"
        EncodingType="wsse:Base64Binary">
        QMwcAG ...
    </wsse:BinarySecurityToken>
</wsse:Security>

    正如该代码片段所示,Kerberos票据是使用更一般的<BinarySecurityToken>元素发送的。该元素的ValueType属性表明这是一个Kerberos Version 5服务票据,它用于验证请求特殊服务的客户端(当发送票据授予票据时,ValueTypewsse:Kerberosv5TGT)。虽然也定义了十六进制编码方案,但是票据本身使用base64编码表示,并且只显示其前几个字节。

    WS-Security定义的第三个方案用于表示安全令牌、X.509证书,它也依赖于<BinarySecurityToken>元素。下面是一个示例:

<wsse:Security
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:BinarySecurityToken
        ValueType="wsse:X509v3"
        EncodingType="wsse:Base64Binary"    >
        KkFPle ...
    </wsse:BinarySecurityToken>
</wsse:Security>

    您可以发现,该示例与先前所述的Kerberos票据示例没有多大区别。此时,<BinarySecurityToken>ValueType属性表明正在发送X.509证书。再次使用了Base64编码,并且证书本身也是该元素内容的一部分,正如Kerberos票据在先前示例中起到的作用一样。

    与在SOAP消息的标头中直接嵌入安全令牌的这三个方案一起,WS-Security还定义了<SecurityTokenReference>元素。正如其名称所示,该元素包含一个指示从何处查找安全令牌的URI。这样,消息接收方就可以从令牌所在地(例如,Internet上的已命名位置)将其取回。该元素也可用于引用包含在该消息的SOAP标头中的安全令牌,在以下部分中将详细说明这一功能的用途。

    WS-Security采用一种非常灵活的方法进行传输和身份验证,然而这里还有一个重要含义:虽然两个系统都符合WS-Security的标准,但二者仍然不能进行相互验证。例如,其中一个系统可能只支持Kerberos,而另一个系统只支持使用X.509证书进行基于数字签名的身份验证。仅允许使用WS-Security是不够的,有关确切地使用何种类型的安全令牌,还需要有一些协议。

完整性(Integrity

    使用SOAP消息进行传输和身份验证是一个多方面的问题,可能存在多种解决方案。因此,WS-Security采用了一种非常广泛的方法。但是,更明确的一点是要为SOAP消息提供完整性。解决方案就是使用某种类型的数字签名。幸运的是,已经有了针对该领域的W 3C 标准。该标准称为“XML签名,它为数字签名XML文档提供了详细的机制。WS-Security并没有彻底改造已有标准,而是简单地利用现有规范,并就如何在SOAP消息中使用这些规范提出了一些具体细节。

    XML签名规范定义的主要内容是<Signature>元素,该元素的内容包括数字签名本身以及有关如何生成该签名的信息。虽然已经有了一些方案,但一个典型的<Signature>实例与SOAP中使用的相同,也包含<SignedInfo><KeyInfo>元素。<SignedInfo>元素描述正在进行签名的信息。该元素本身包含多个子元素,每个子元素都指定了一些有关已签名信息的内容。其中最重要的子元素包括以下元素:

标识用于在生成签名之前将此XML文档转换为标准形式的算法。

    这个过程是必需的,因为要使数字签名生效,已签名文档的每一方视图都必须逐位相同。然而,如果不进行标准化,那么两个语义相同的XML文档可能会在位级上存在区别。例如,其中一个可能表示带有回车/换行符对的分行符,而另一个可能只使用换行符。标准化可将XML文档转换为标准形式,从而确保双方在签名之前能够以相同的方式查看文档。

标识用于创建数字签名的算法。

    XML签名标准和WS-Security均要求支持数字签名标准(使用安全哈希算法(SHA)-1DSA算法创建消息摘要),也建议支持使用SHA-1RSA算法。

<Reference>标识正在进行签名的信息以及对其进行的任何转换。

    SOAP一同使用时,该部分签名一般引用此SOAP消息的已签名部分,例如,正文和标头部分。<Reference>元素还包含从已签名信息生成的base64编码的消息摘要,并指定诸如SHA-1等用于创建摘要的算法。

<SignatureValue>包含构成数字签名的字节。

<KeyInfo>指示验证签名时应使用的密钥。

    密钥可以用多种方式进行标识,例如引用一个包含适当公钥的证书。由于接收方可能会通过其他手段了解要使用的密钥,因此甚至可以完全忽略该元素。

    倘若了解XML签名的<Signature>元素的这种基本特性,就可以理解WS-Security是如何使用该元素的。代码段2是包含数字签名的SOAP消息形式的一个示例。

代码段2 包含数字签名的SOAP消息:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope
    xmlns:s="
http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext"
    xmlns:wsu="
http://schemas.xmlsoap.org/ws/2002/07/utility">
    <s:Header>
        <wsse:Security>
            <wsse:BinarySecurityToken
                ValueType="wsse:X509v3"
                EncodingType="wsse:Base64Binary"
                wsu:Id="X509Cert"            >
                KkFPle ...
            </wsse:BinarySecurityToken>
            <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod
                        Algorithm="http://www.w3.org/2001/10/xml-exc-c14N"/>
                    <ds:SignatureMethod
                        Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/
                    <ds:Reference URI="#MessageBody">
                        <ds:DigestMethod
                           Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                        <ds:DigestValue>
                            aOb4Luuk...
                        </ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>
                    A9qqIrtE3xZ...
                </ds:SignatureValue>
                <ds:KeyInfo>
                    <wsse:SecurityTokenReference>
                        <wsse:Reference URI="#X509Cert"/>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
            </ds:Signature>
        </wsse:Security>
    </s:Header>
    <s:Body wsu:Id="MessageBody">
        ...
    </s:Body>
</s:Envelope>

    在本例中,标头的<Security>元素以<BinarySecurityToken>开头。该元素与前面部分中所示的X.509证书示例几乎完全相同。唯一的区别在于,该元素使用由Web服务安全性附录定义的Id属性来为该<BinarySecurityToken>提供名称。此处的Id属性值为“X509Cert”,从标头的其他位置可以引用该属性值。您不久将会看到,当消息中也包含数字签名时,这个特性非常有用。接下来是由XML签名标准定义的<Signature>元素,它包括前面描述的几个子元素:<SignedInfo><SignatureValue><KeyInfo><SignedInfo>元素内包含用于对该XML文档进行标准化以及创建其数字签名的算法的标识符。<Reference>元素具有一个URI属性,它可以准确指定正在进行签名的内容。在本示例中,仅对正文进行了签名,因此,这个URI与消息的<Body>元素所关联的Id属性值相匹配。Reference元素也包含两个子元素:<DigestMethod><DigestValue>。其中,第一个子元素标识用于创建这个数字签名的消息摘要的算法,而第二个子元素包含消息摘要值本身。由于在本例中仅对正文进行了签名,因此,这个摘要是从SOAP消息的<Body>元素的标准化版本中计算得出的。接下来的<Signature>子元素<SignatureValue>包含数字签名本身的字节,该数字签名通过使用签名者的私钥对消息摘要进行加密而创建的。最后是<Signature>中的最后一个子元素<KeyInfo>,它标识验证这个签名应使用的公钥的位置。在本示例中,消息中先出现那个密钥(在安全令牌中),然后通过<SecurityTokenReference>进行引用。使用该密钥的Id属性"X509Cert"对其进行标识。

    对于许多Web服务应用程序,确保数据完整性至关重要。具有一种经过良好定义并被广泛接受、可为SOAP提供这种服务的方法也非常有用。由于提供有效的签名和受信任的证书证明了专用私钥的知识,对于身份验证,使用公钥技术创建的数字签名也非常有用,验证某人的身份亦是如此。然而,在实际应用中创建XML文档的数字签名并不是最简单的事情。准确地说,必须首先标识要进行签名的内容,然后进行标准化,再进行实际签名。由于WS-Security允许为相同的消息创建多个签名,每个签名可能由消息途径中不同的接收方所创建,并且每个签名可能传输消息的不同部分或存在重叠的部分,因此,它可能比此处所示的示例要复杂得多。根据W 3C XML签名标准来构建所有这些内容非常有意义,但是使用这种WS-SecuritySOAP标头一定会比那些不需要特定安全服务的要大得多、复杂得多。

保密性(Confidentiality

    对于许多重要的应用程序来说,防止数据在传输中被人窥探,并确保其安全性非常重要。因此,WS-Security定义的第三个服务是保密性,它提供了一种在SOAP消息传输之前对其进行部分加密或全部加密的方法。WS-Security的设计者以同样的方式解决了完整性问题,他们选择了在现有保密标准的基础上构建保密性,而不是创建全新的标准。他们再一次从W 3C 的现有标准中选择了一个称为“XML加密的规范。通过该标准,WS-Security允许对SOAP消息的标头信息、正文以及任何附件进行部分加密或全部加密。XML加密规范并不是一种十分复杂的文档。例如,WS-Security仅使用了由该标准定义的三个XML元素:<EncryptedData><EncryptedKey><ReferenceList>。其中最重要的自然是<EncryptedData>。正如其名称所示,该元素包含子元素中称为<CipherData>的实际加密数据。该元素还可以包含指示所使用的加密算法的子元素、加密所使用的密钥以及其他内容。代码段3显示了一个示例,说明发送方选择对按WS-Security定义的消息正文进行加密时,一个简单的SOAP消息的形式。

代码段3 加密之后的SOAP消息:

<s:Envelope
    xmlns:s="
http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ds="
http://www.w3.org/2000/09/xmldsig#"
    xmlns:xenc="
http://www.w3.org/2001/04/xmlenc#">
    <s:Body>
        <xenc:EncryptedData>
            <EncryptionMethod
                Algorithm='
http://www.w3.org/2001/04/xmlenc#tripledes-cbc'/
>
            <ds:KeyInfo>
                <ds:KeyName>
                    CN=Key13, C=US
                </ds:KeyName>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>
                    r5KipsDV . . .
                </xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </s:Body>
</s:Envelope>

    首先注意消息中没有出现SOAP标头。尽管这在实际应用程序中是不可能的,但可能会使用由WS-Security定义的XML加密,而不含有Security元素或任何其他Header元素。在这个简单的示例中,消息正文仅包含一个带有三个子元素的<EncryptedData>元素。其中第一个子元素<EncryptionMethod>指示加密数据时所使用的算法。在本示例中,选择了对称算法TripleDES,并且使用相同的密钥来加密和解密数据。接下来的子元素是从XML签名中借用的<KeyInfo>。此时,假设双方均已知道可以在加密和解密中使用的所有密钥,因此,唯一要做的就是通知选定的接收方。虽然密钥可以使用任意名称,但是也可以使用LDAP风格的识别名称来命名密钥。因此,该示例指定密钥名为“CN=Key13, C=US”。无论使用何种名称,重要的是双方均可以准确地了解该名称所引用的密钥。最后是<CipherData>子元素,它在其<CipherValue>子元素中带有实际加密数据的base64编码。

    也可能在相同的消息中传输加密的密钥,这个消息带有使用该密钥进行加密的数据。当使用对称密钥加密数据时,就经常会出现这种情况,如图3中的TripleDES示例所示,然后使用消息接收方的公钥对对称密钥进行加密并随数据一道发送。消息到达时,接收方可以使用其私钥解密嵌入的对称密钥,然后使用该对称密钥对实际数据进行解密。为了发送加密的密钥,XML加密定义了一个具有识别名<EncryptedKey>的元素。为了与SOAP消息一起使用,WS-Security指定了该元素应当出现在<Security>标头中。因此,带有加密数据和读取该数据所需的加密对称密钥的SOAP消息可能如代码段4所示。

代码段4 带有密钥的加密SOAP消息:

<s:Envelope
    xmlns:s="

http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext"
    xmlns:wsu="
http://schemas.xmlsoap.org/ws/2002/07/utility"
    xmlns:ds="
http://www.w3.org/2000/09/xmldsig#"
    xmlns:xenc="
http://www.w3.org/2001/04/xmlenc#">
    <s:Header>
        <wsse:Security>
            <xenc:EncryptedKey>
                <xenc:EncryptionMethod
                    Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                <ds:KeyInfo>
                    <ds:KeyName>
                        CN=Key13, C=US
                    </ds:KeyName>
                </ds:KeyInfo>
                <xenc:CipherData>
                    <xenc:CipherValue>
                        ir4DfG . . .
                    </xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                    <xenc:DataReference URI="#EncryptedBody"/>
                </xenc:ReferenceList>
            </xenc:EncryptedKey>
        </wsse:Security>
    </s:Header>
    <s:Body>
        <xenc:EncryptedData wsu:Id="EncryptedBody">
            <xenc:EncryptionMethod
                Algorithm='
http://www.w3.org/2001/04/xmlenc#tripledes-cbc'/>
            <xenc:CipherData>
                <xenc:CipherValue>
                    r5KipsDV . . .
                </xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </s:Body>
</s:Envelope>

    与代码段3中虚拟的简单示例不同,代码段4中的SOAP消息包含了带有Security元素的标头。这个元素只包含XML加密标准中定义的<EncryptedKey>子元素。<EncryptedKey>的格式与<EncryptedData>的格式非常相似,在此示例中,它具有三个熟悉的子元素:<EncryptionMethod><KeyInfo><CipherData>。此处要进行加密的是对称密钥,因此,<EncryptionMethod>描述的是如何对该密钥进行加密,而不是如何对实际数据进行加密。由于我们一直假设这是使用接收方的公钥进行加密的对称密钥,因此,该元素指示对这个密钥进行加密时使用的RSA算法。<KeyInfo>元素指定作为此<EncryptedKey>的一部分进行传输的对称密钥的名称,并且由于我们假设该密钥与前面示例中的相同,因此,它具有相同的名称。与先前的<EncryptedData>元素不同,此<EncryptedKey>中的<CipherData>元素包含加密的对称密钥,而不是任何用户数据。

    <EncryptedKey>元素还具有<EncryptedData>所没有的一个新的子元素。该元素<ReferenceList>在将这个密钥与使用其进行加密的数据相关联的过程中发挥了重要作用。它包含一个标识该SOAP消息部分的URI,该消息是使用<EncryptedKey>元素中包含的密钥进行加密的。在代码段4中,整个SOAP体都使用这个密钥进行加密,因此,使用了一个相当刻板的名称——“EncryptedBody”SOAP体本身的形式与代码段3中所示的非常类似。一个区别是,<EncryptedData>元素的开始标记现在具有一个名为“EncryptedBody”Id属性。如上所述,这就是将这个元素包含的数据与用于对该数据进行加密的密钥相关联的方法。其他区别是,由于已经明确地标识出对这个元素的内容进行加密的密钥,因此不需要<EncryptedData>中的<KeyInfo>元素。

    按照WS-Security定义,对SOAP消息使用XML加密的方式有多种。您可以对整个正文、正文和某些标头元素、仅正文的某些部分或者随消息一道发送的附件进行加密。SOAP消息的不同接收方可以添加自己的加密标头,或解密并处理他们预期的部分。由于Web服务中对保密性的要求是多样化的,因此定义如何实现保密性的标准必须是完全通用的。

    虽然WS-Security在规定使用SOAP提供安全性的基础方面做了许多有用的工作,但它并不是面面俱到的。因此,还制定了许多其他规范来填补其中的一些空白。下面来看看它们定义的这些文档和技术。

指定策略:WS-SecurityPolicy

    WS-SecurityPolicy就以WS-Policy规范(由MicrosoftIBM和其他公司联手创建)为基础,定义了可用于指定安全相关策略的XML元素。由于这些元素允许Web服务明确地指定其策略,因此它们被称为断言

    只要使用安全机制,就必须存在某些类型的安全策略。这些策略阐明了针对特殊情况的特定安全要求。例如,对于使用WS-SecurityWeb服务,许多细节都需要详细说明。这种服务是否接受用于身份验证的Kerberos票据、X.509证书以及数字签名,还是别的什么东西?接受哪种数字签名算法?支持使用哪些加密算法来提供保密性?回答此类问题就意味着定义了安全策略。

    当然,除了安全性以外,策略在其他领域中也非常有用。因此,MicrosoftIBM和其他公司联手创建了WS-Policy规范。这个文档定义了一种为Web服务指定各种策略的一般方法。WS-SecurityPolicy就以此为基础,定义了可用于指定安全相关策略的XML元素。由于这些元素允许Web服务明确地指定其策略,因此它们被称为断言。由WS-SecurityPolicy定义的断言包括以下几种:

<SecurityToken>允许Web服务指定它将接受哪些类型的安全令牌以及它所信任的令牌发行方。

<Integrity>允许Web服务指定它将接受的有关数字签名的多种选项,例如用于创建消息摘要的算法。

<Confidentiality>允许Web服务指定有关应如何执行加密的选项,例如所使用的加密算法。

<Visibility>允许Web服务指定消息的哪些部分必须进行解密。

    WS-SecurityPolicy没有定义如何准确地从设计者向任何感兴趣的客户端传输安全策略。表示策略的XML元素可以通过SOAP消息发送,也可以通过其他方式传输。但是,WS-Policy定义了一个通用的<Policy>元素,它可以包含一个或多个策略断言。以下是一个简单的示例,它说明了对于要求使用Kerberos票据进行身份验证的Web服务,<SecurityToken>断言的形式:

<wsp:Policy
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:SecurityToken wsp:Usage="wsp:Required">
        <TokenType> wsse:Kerberosv5ST</TokenType>
    </wsse:SecurityToken>
</wsp:Policy>

    <Policy>元素指定了在WS-PolicyWS-Security中定义的命名空间,并且只包含<SecurityToken>子元素。该子元素的使用被标记为Required,这意味着Web服务需要遵守这个策略。换句话说,正如<TokenType>元素所指示的那样,这个特定的Web服务现在只接受Kerberos票据作为身份验证的基础。单个的<Policy>元素可以包含有关安全令牌、完整性以及其他方面的策略。还有其他几个选择,包括指定相关首选项的方法。例如,Web服务可以定义一个<SecurityToken>,允许客户端使用KerberosX.509证书进行身份验证,然后指出优先使用Kerberos。但是,无论使用哪种方案,策略值都是显而易见的。通过提供一种明确的方法以便Web服务声明其安全要求,它们使客户端能够明白要访问该服务所必须做的事情。

获得安全令牌:WS-Trust

    安全令牌是WS-Security的基础,但是它们只是魔法般地出现,并没有定义分发它们的机制。事实是,正如已经存在的各种安全令牌一样,能够分发它们的软件服务已经存在了。例如,要获得Kerberos票据,可以与Kerberos密钥发行中心(Key Distribution Center KDC)联系;要获得X.509证书,则可以与证书颁发机构(Certification AuthorityCA)联系。尽管WS-Security定义了如何在标准XML内包装Kerberos票据和X.509证书以便在SOAP消息中进行传输,但它没有定义使用SOAPKDCCA或者能够分发安全令牌的任何其他服务进行交谈的方法。


1 WS-Trust

    WS-Trust修正了这个问题。这个规范定义的主要内容是从一些安全令牌服务(例如KDCCA)请求安全令牌的机制,图1对这一观点进行了解释。假设客户端希望调用Web服务AWeb服务B,并进一步假设Web服务A需要Kerberos票据进行身份验证,而Web服务B需要数字签名以及相匹配的X.509证书。如图所示,客户端可能会首先向安全令牌服务X(实际上是KDC)发出SOAP请求,以请求包装在<BinarySecurityToken>内部的Kerberos票据。然后调用Web服务A,将最新获得的令牌传递给SOAP消息的<Security>元素。接下来,客户端可以向安全令牌服务Y(即CA)发出SOAP请求,以请求X.509证书。在证书返回后,客户端就可以调用Web服务B,以同时传递这个证书和匹配的数字签名。

    WS-Trust定义了向安全令牌服务进行请求的形式,以及如何返回响应。这种交互依赖于两个元素:<RequestSecurityToken><RequestSecurityTokenResponse>。其基本思想是发送包含<RequestSecurityToken>作为其正文的SOAP消息,然后获得包含<RequestSecurityTokenResponse>SOAP消息以及新的安全令牌。代码段5显示了请求消息的一个简单示例:

代码段5 请求消息:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope
    xmlns:s="
http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext"
    xmlns:wsu="
http://schemas.xmlsoap.org/ws/2002/07/utility">
    <s:Header>
        <wsse:Security>
            <wsse:UsernameToken wsu:Id="MyCert">
                <wsse:Username>Diana</wsse:Username>
                <wsse:Password>mY5ecRet</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </s:Header>
    <s:Body>
        <wsse:RequestSecurityToken>
            <wsse:TokenType>wsse:X509v3</wsse:TokenType>
            <wsse:RequestType>wsse:ReqIssue</wsse:RequestType>
            <wsse:Base>
                <wsse:Reference URI="#MyCert"/>
            </wsse:Base>
        </wsse:RequestSecurityToken>
    </s:Body>
</s:Envelope>

    Security标头包含了一个<UsernameToken>,以便对这个请求进行身份验证。尽管在通过加密的SSL连接发送请求时,此处使用的简单选择可能是合理的,但是以明文形式发送这个请求可能要求同时包含数字签名和时间戳的更健壮的安全令牌。消息正文包含了请求颁发X.509证书的<RequestSecurityToken>元素。假设请求成功,由安全令牌服务返回的响应正文可能如下所示:

<s:Body>
    <wsse:RequestSecurityTokenResponse>
        <wsse:RequestedSecurityToken>
            <wsse:BinarySecurityToken
                ValueType="wsse:X509v3"
                EncodingType="wsse:Base64Binary">
                KkFPle ...
            </wsse:BinarySecurityToken>
        </wsse:RequestedSecurityToken>
    </wsse:RequestSecurityTokenResponse>
</s:Body>

    请求的证书被返回,它包装在由WS-Security定义的<BinarySecurityToken>元素中。虽然在示例中没有显示,但是也可能会返回与这个证书的公钥相关联的私钥。要允许这种情况,WS-Trust定义了一个<RequestedProofToken>元素,以便为其他类型的安全令牌包含这种或类似的信息。

    WS-Trust还为基本的<RequestSecurityToken>元素定义了相当多的扩展。其中包括用于请求在构建所请求的安全令牌时使用的特定算法和密钥大小的选项。例如,请求方可以要求:应该使用带有1024位密钥的RSA算法来创建数字签名。除了请求方之外,还有一个代表某个人请求安全令牌的机制。第三个扩展提供了一个指定安全令牌的生存期以及该生存期是否可以更新的方法。WS-Trust还定义了在向安全令牌服务请求安全令牌时,可以选择使用的质询/响应机制。尽管在某些情况下,直接的身份验证机制(如图1中所示的机制)可能很好,但是安全令牌服务可能会需要有关正在交谈一方的更多证据。如果像上面的示例中那样,请求中没有包含时间戳会怎么样?安全令牌服务如何才能确定这不是先前请求的重发,而是由攻击者发送的请求?为了避免出现这种情况,安全令牌服务可能会要求请求方对一组特定的信息进行数字签名,然后在发出被请求的安全令牌之前验证该签名。

建立上下文:WS-SecureConversation

    WS-SecureConversation 自身不为 Web 服务提供完整的安全解决方案。WS-SecureConversation 是一个构建块,它与其他 Web 服务和特定应用程序协议一起使用,以适应各种各样的安全模型。

    有时,解决一个问题所需要的全部过程只是一个或两个SOAP消息的简单交换。例如,调用一个远程操作可能只要求这种简单的交换。但是,假设一个应用程序可能需要通过调用一系列操作才能与其他某个应用程序交换大量的SOAP消息。在这种情况下,在两个应用程序之间创建某个类型的共享安全上下文会非常有用。这种共享上下文的一个常见用法是,为将用于上下文周期的加密密钥定义一个生存期。例如,通讯双方可能希望创建一个对称密钥,然后使用它来加密通过特定安全上下文的生存期进行交换的信息(这种非Web服务的一个示例就是SSL,它能够创建一个对每个会话中所传输的字节进行加密的新密钥)。

    WS-SecureConversation定义了XML类型和交互,以允许建立安全上下文和创建特定于此上下文的密钥——即只用于特定会话的密钥。这些机制的基础是<SecurityContextToken>元素。正如该规范所定义的那样,每个安全上下文都具有一个名称和共享的机密,因此<SecurityContextToken>可以包含<Identifier>子元素,以唯一地指定这个上下文以及用于该上下文的一个或多个加密密钥的名称。

    WS-SecureConversation定义了创建<SecurityContextToken>的三种可能的方法:

    第一,可以从某些安全令牌服务请求<SecurityContextToken>。要实现这个目的,请求方应在正文中向安全令牌服务发送包含<RequestSecurityToken>元素的SOAP消息,就如同请求普通的安全令牌一样。服务通过SOAP消息进行响应,消息正文包含<RequestSecurityTokenResponse>元素,该元素又包含所请求的<SecurityContextToken><RequestedProofToken>,而这两者又包含这个新上下文的共享机密,例如已加密的对称密钥。

    第二,可由通讯的其中一方创建<SecurityContextToken>并将其发送到另一方。在这种情况下,<SecurityContextToken>的创建者在包含<RequestSecurityTokenResponse>SOAP消息中发送新的令牌(开始不发送<RequestSecurityToken>)。这个消息与前面示例中从安全令牌服务获得的消息相同,因此它包含有新的<SecurityContextToken><RequestedProofToken>

    第三,可以通过将使用该上下文的双方之间的协商来创建<SecurityContextToken>。其中一方向另一方发送包含<RequestSecurityToken>SOAP消息,然后接收包含<RequestSecurityTokenResponse>的响应。虽然这不是必需的,但是这种交换可能会依赖先前描述的WS-Trust定义的质询/响应协商过程。如果协商成功,其结果是双方都以新的<SecurityTokenReference><RequestedProofToken>结束。

    无论通过什么方法创建,安全上下文始终包含共享的机密,例如对称密钥。虽然这个密钥可直接用于消息加密或签名,但是WS-SecureConversation不建议这样做。相反,从安全上下文的共享机密中派生一个或多个密钥,然后使用派生的密钥进行通讯,是一种更为安全的方法。本规范是基于传输层安全性(Transport Level Security TLS)规范中使用的方法,来定义一个用于创建派生密钥的算法。也可以使用其他方法来生成派生密钥,因为规范并没有要求使用它所定义的算法。一旦创建了安全上下文,所需的全部操作就是标识每个SOAP消息中的上下文。由于上下文存在某种提示,因此通讯的每一方都已经知道要使用哪个(或哪些)密钥来处理这个消息。有了上下文以后,使用它的SOAP消息的Security元素将包含具有该上下文唯一标识符的<SecurityContextToken>元素。通过对这个标识符进行检查,消息的接收方就可以确定所使用的安全上下文。如今,在SSLKerberos中的使用表明,与其他安全技术相比,安全上下文是较好的;WS-SecureConversation使得它们能够在Web服务应用程序中使用。

使用SAML和其他基于XML的令牌

    “Web Services Security Profile for XML-based Tokens”定义了将基于XML的安全令牌与WS-Security结合使用的一般方法,然后指定了如何使用这两种现有类型的XML令牌。这个规范声明的第一类XML安全令牌是使用安全断言标记语言定义的。

    正如本文前面所述的那样,WS-Security定义了两个用于表示安全令牌的XML元素。但是其他类型的令牌是怎么样的呢?尤其是已经使用XML定义的安全令牌?WS-Security本身并没有说明这种类型的令牌应当如何表示,因此一个称为“Web Services Security Profile for XML-based Tokens”的规范对这个问题进行了修正。它定义了将基于XML的安全令牌与WS-Security结合使用的一般方法,然后指定了如何使用这两种现有类型的XML令牌。这个规范声明的第一类XML安全令牌是使用安全断言标记语言(Security Assertion Markup Language SAML)定义的。虽然SAML可能是相当普及的技术,但理解它具有重要的意义——如果您是一位失眠症患者,则SAML规范的副本所起的作用就像不能进入睡眠时所施的入睡魔法。正如其名称所示,该语言允许您表达有关诸如人或应用程序等主题的广泛断言。这些断言可以有关身份验证(如何才能完成)、授权(是否赋予对特定资源的访问权)或其他内容。尽管这不是必需的,但可以使用XML签名对断言本身进行身份验证。

    SAML断言可以直接插入SOAP标头的<Security>元素中,而不是定义另一种类型的安全令牌元素。与Kerberos票据或X.509证书不同,SAML断言已经以XML进行了表述,因此易于使用。稍微简化的结果如代码段6所示。如本示例所示,SAML Assertion元素可以原始形式插入到Security元素中。尽管本示例中没有显示,但AssertionID属性可以将这个SAML安全令牌与该SOAP消息中的数字签名或其他内容相关联。

代码段6 SAML断言:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope
    xmlns:s="
http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsse="
http://schemas.xmlsoap.org/ws/2002/12/secext"
    xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
    <s:Header>
        <wsse:Security>
            <saml:Assertion
                MajorVersion="1"
                MinorVersion="0"
                AssertionID="SecurityToken-ef375268"
                Issuer="dcatignani"
                IssueInstant=" 2003-05-23 T11:04:15.8357639-08:00"            >
                ...
            </saml:Assertion>
        </wsse:Security>
    </s:Header>
    <s:Body>
        ...
    </s:Body>
</s:Envelope>

    Web Services Security Profile for XML-based Tokens规范声明的其他类型的XML安全令牌是XrMLXrML允许您表达有关数字内容或服务的权限,例如访问特定Web服务或播放特定音频文件的权限。它定义了一个<license>元素,该元素可以通过与SAML <Assertion>相同的方式插入到SOAP标头的Security元素中。

    SAMLXrML是相对较新的技术,因此您可能暂时还没有看到用于SOAP的这些选项。然而,随着时间的推移,其中一种或两种技术都可能会变得非常普及,也可能会出现其他基于XML的令牌。提供在SOAP消息中包含这些令牌的标准方法很有意义。

小结

    有效的安全性对于Web服务至关重要。倘若已经拥有大多数所需的技术(问题仅仅是将这个现有的安全技术映射到XMLSOAP),您可能会认为WS-Security及其关联的规范非常简单(本文可能就会非常简练)。然而,要适应目前使用的多种多样的安全机制,以及为将来出现的新技术留有余地,则要求有一组重要的技术。一旦出现这种技术,我们所有人都希望见到的安全和可互操作的Web服务就会成为现实。虽然我们彼此都不了解,但我仍然迫切盼望这一天的到来。

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值