`

UsernameToken 介绍(转)

阅读更多

很好的一篇文章,转过来收藏一下

 

转自:http://blog.csdn.net/cocojiji5/archive/2008/12/08/3478507.aspx

 

使用用户名和密码来验证用户的身份是最普通也最常见的方法,虽然在安全性方面也比较弱,由于其运用的广泛性还是成为了WS-Security目前所支持的Security Token之一。其原理非常简单,用户在发送请求的时候,在Soap head中加入自己的用户名以及密码,接受请求的Service通过之前与Client建立的共享密码来验证密码的合法性从而实现鉴别用户的功能。

不过实际运用起来就不能考虑的那么简单了,该方法主要存在两个问题:
1. 在SOAP包中传输密码怎么保证密码的安全性?
2. 怎么从用户名密码中获得签名和加密所需要的密钥?

针对第一个问题有三种解决方案:
1. 使用运输层的安全协议(如SSL)来保证明文密码的安全性。
2. 对明文密码做摘要后再传送给Service。
3. 利用从密码派生出来的密钥来代替直接使用密码来实现身份鉴别。

 

第一种方法采用了WS-Security结合运输层的安全协议(SSL)来保证密码的安全,在本系列一开始的文章已经描述过运输层安全协议的缺点,所以在此不对该方法做详细介绍。

 

第二种方法类似于HTTP Digest Authentication,先来看一段使用该方法的示例:

 

<wsse:UsernameToken>
    <wsse:Username>NNK</wsse:Username>
    <wsse:Password Type="...#PasswordDigest">
         weYI3nXd8LjMNVksCKFV8t3rgHh3Rw==
    </wsse:Password>
    <wsse:Nonce>WScqanjCEAC4mQoBE07sAQ==</wsse:Nonce>
    <wsu:Created>2003-07-16T01:24:32Z</wsu:Created>
</wsse:UsernameToken>

 

从中看出这里使用了PasswordDigest类型的Password,从Password的内容也可以看出这里没有使用明文密码的形式。另外还多出了wsse:Nonce和wsu:Created两个元素。


其中Password的内容的计算公式如下:

Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )

 

读者可能比较奇怪wsse:Nonce和wsu:Created这两个元素的作用。为什么不直接SHA-1(password) ? 这样做是为了避免重放(Replay)攻击。假设Alice以摘要的形式向Service发送了密码,如果Bob此时截获了Alice发送的密码摘要,然 后再用它向Service发送请求,那么Service将误认为Bob也是合法用户。当我们加入Nonce和Created元素之后,Service可以 检查收到的消息中的Nonce是否已经收到过了,或者在一段时间(5min)内是否收到了相同用户名密码,从而避免重放攻击的危险。不过使用 PasswordDigest方式要求Service必须拥有密码的明文形式,也就是说Service可以看到每个用户的密码,这对用户来说增加了风险。 因为通常情况下用户的密码是以hash的形式保存在Service端的,从而保证用户的信息不被泄漏。
尽管通过PasswordDigest可以 避免密码的明文传播,而且通过引入wsse:Nonce和wsu:Created可以避免重放攻击的危险,但是如果Bob能够把传送中的密码摘要完全的拦 截下来(使它无法传送到Service),然后利用拦截下来的密码去冒充Alice去请求Service,那么Service将束手无策。为此,我们引入 了第三种方法。

 

第三种方法和Kerberos协议 中KDC向Client传送TGT的方式类似。

 

我们可以看出前两种方式用户都将自己的密码发送给Service用于身份鉴别,难道为了证明自己的身份就必须把密钥(这里是密码)直接告诉别人吗?其实问题 的关键在于Client能向Service证明它拥有只有C与S知道的密钥。而证明拥有的最直接方法就是告诉对方这个密钥,然后由Service比较这个 密钥是否和它所知道的密钥一致,从而鉴别用户的身份。但是这种方法如前所述存在多种缺陷。既然仅仅需要Client证明它知道这个密钥,那么Client 可以用这个密钥对一段消息做一个签名,然后将消息和签名同时发送给Service,Service用它所知道的Client的密钥也对同样的消息做一次签 名,通过比较两个签名是否一致就可以确认Client是否真的拥有它的密钥。同样通过加密的方法Client也可以向Service证明自己是否真的拥有 密钥(因为只有C与S密钥一致Service才能解密出用C密钥加密的消息)。这样一旦Client在消息中加入自己的一些特有信息(比如IP),即便 Bob截获了消息但是由于他并不知道真正的密钥,看不到那些特有信息,也就无法冒充Alice。

 

通过这种间接证明拥有密钥的方法,我们同时解决了文章一开始提出的第二个问题:
怎么从用户名密码中获得签名和加密所需要的密钥?

只要对密码做一些处理就可以从中派生出密钥。当然为了安全起见我们希望每次派生出来的密钥都不一样,这样就可以避免多次使用同一密钥而导致密钥被破解。下面就是WS-Security对密钥派生的元素定义:

 

<wsse:UsernameToken wsse:Id=”…”>
    <wsse:Username>…</wsse:Username>
    <wsse11:Salt>…</wsse11:Salt>
    <wsse11:Iteration>…</wsse11:Iteration>
</wsse:UsernameToken>

 

其中Salt是导致密钥变化的因子,Iteration是密钥派生时Hash的次数。
密码的派生公式如下:
K1 = SHA1( password + Salt) 
K2 = SHA1( K1 )
   …
Kn = SHA1 ( Kn-1 )

 

可以看到此时在UsernameToken已经不再包含Password元素,因为Client将通过使用从Password派生出密钥做签名做加密的方式来证明它拥有密钥,从而证明自己的身份。

由此看出第三种办法相对来说安全性大大提高了,但是在实际应用中以上介绍的三种的方法都不被推荐使用。

 

第三种方法仍旧存在以下两个缺陷:

 

1. 直接使用密码派生密钥,同以往临时产生的会话密钥相比,密码一旦破解,所有由改密码派生的密钥也被破解。由于密码长期不变, 那么随后所有使用该密码加密的消息都没有安全性可言。而且该密码可能还被用于Client与其他Service的交互,那么被破解后带来的损失就大多了。

 

2. 用户密码必须以明文形式保存在Service端。

因此,在微软的WSE对安全的默认支持方式中采用了UsernameToken和Service端Certification的组合的方式来表示Security Token。下图就是WSE中已经实现的UsernameForCertificate对SOAP Envelop的扩展结构。

 


             

 

从中可以看到SOAP Head中的wsse:UsernameToken已经被加密,被xenc:EncryptedData所替代,查看其Token Reference发现加密使用的Key来自xenc:EncryptedKey。如果你完整阅读了本系列的文章,你将不会对它太陌生,在XML Encryption 中曾经对它的来由做了详细介绍。

       Note 由于使用 对称密钥加密效率高,所以通常会使用对称密钥来加密数据,但是如何让消息的接受也获得对称密钥则成了一个问题。消息发送方不可能将对称密钥也随消息传递给 消息接收方,此时利用非对称密钥来实现加密所用的对称密钥的传递成为了一个比较好的选择。EncrptedKey就是实现此种功能的扩展元素。


Client随机产生了一个对称密钥并用它来加密和签名SOAP Envelop中的其他元素(如UsernameToken),然后通过使用Service(消息接受方)的公钥(由于是公钥可以方便获取)来加密该对称 密钥,以保证只有Service能够获得Client随机产生的对称密钥,从而达到验证消息完整性,解密数据以及鉴别用户身份的目的。以下是采用这种方式 保证安全的SOAP Envelop的示例:

<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc"
    xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
    <SOAP-ENV:Header>
        <wsse:Security
            xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/secext">
            <wsse:UsernameToken>
                <wsse:Username>HotelService</wsse:Username>
                <wsse:Password>myword</wsse:Password>                          
            </wsse:UsernameToken>
            <xenc:EncryptedKey wsu:id="userSysmetricKey">
                <xenc:EncryptionMethod
                    Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                 <ds:KeyInfo>
                       <wsse:SecurityTokenReference>
                           <wsse:KeyIdentifier  
                            ValueType="...oasis-wss-soap-message-security-1.1#ThumbPrintSHA1">
                                    LKiQ/CmFrJDJqCLFcjlhIsmZ/+0=
                           </wsse:KeyIdentifier> 
                       </wsse:SecurityTokenReference>
                    </ds:KeyInfo>
                <xenc:CipherData>
                    <xenc:CipherValue>G2wDCq24FsgBGerE...</xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                    <xenc:DataReference URI="#DiscountResponse"/>
                </xenc:ReferenceList>
            </xenc:EncryptedKey>
            <ds:Signature>
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod
                        Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    <ds:SignatureMethod
                        Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
                    <ds:Reference URI="#DiscountedBookingForPartnersResponse">
                        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
                        <ds:DigestValue>JwFsd3eQc0iXlJm5PkLh7...</ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>BSxlJbSiFdm5Plhk...</ds:SignatureValue>
                    <ds:KeyInfo>                  
                          <wsse:SecurityTokenReference>
                               <wsse:Reference URI="#userSysmetricKey"
                            ValueType="...oasis-wss-soap-message-security-1.1#EncryptedKey"/>
                          </wsse:SecurityTokenReference>
                    </ds:KeyInfo>
            </ds:Signature>
        </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body wsu:Id="DiscountedBookingForPartnersResponse">
        <s:GetSpecialDiscountedBookingForPartnersResponse
                xmlns:s="http://www.MyHotel.com/partnerservice ">
            <xenc:EncryptedData
                wsu:Id="DiscountResponse"
                type="http://www.w3.org/2001/04/xmlenc#Element">
                <xenc:EncryptionMethod
                    Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc "/>
                <CipherData>
                <CipherValue>XD6sFa0DrWsHdehrHdhcW0x...</CipherValue>
                </CipherData>
            </xenc:EncryptedData>
        </s:GetSpecialDiscountedBookingForPartnersResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>  
  Note 以上介绍的方法UsernameForCertificate仅被WS-Security1.1支持。因为在1.1中才支持使用对称密钥签名。



如此,之前所提到的问题都可以解决了,让我们回顾一下:
Q: 在SOAP包中传输密码怎么保证密码的安全性?
A: 使用密钥加密,只有接受方能解密密码。


Q:
怎么从用户名密码中获得签名和加密所需要的密钥?
A:   随机产生密钥,并通过接受方的公钥加密,保证密钥不被别人所知。

Q: 如何避免重放攻击?
A: 由于其他人无法获得密钥,所以即便截获消息也无法冒充。

Q: 直接使用密码派生密钥被破解了怎么办?
A: 密钥不再从密码派生,而是每次随机产生,即便被破解也不会影响其他的消息和其他的服务。

Q: 用户密码必须以明文形式保存在Service端?
A: 由于密码被加密而不是做摘要所以不需要Service拥有明文密码。

应用场景:
B2C网上购物,每个用户都有各自的用户名密码,而且可以方便的获得Server端的Certification。(比如Amazon)


参考资料:
OASIS Kerberos Token Profile 1.1
Protect Your Web Services Through The Extensible Policy Framework In WSE 3.0

 

 

 

分享到:
评论

相关推荐

    UsernameToken WSE30

    【UsernameToken WSE30】是一个关于Web服务安全(WSE,Web Services Enhancements)3.0版本中UsernameToken身份验证机制的应用实例。在Web服务领域,安全性是至关重要的,而UsernameToken是一种基本的身份验证方式,...

    Sample WS-Security UsernameToken身份验证

    "Sample WS-Security UsernameToken身份验证" 这个标题表明我们要讨论的是一个示例项目,它利用了WS-Security标准中的UsernameToken机制进行身份验证。WS-Security,全称Web Services Security,是用于在Web服务中...

    arm-linux实现onvif server+WS-UsernameToken令牌验证

    在本文中,我们将深入探讨如何在ARM Linux平台上实现ONVIF服务器,并结合WS-UsernameToken令牌验证机制。ONVIF(开放网络视频接口论坛)是一个国际标准,旨在推动网络视频设备之间的互操作性。它定义了一套通信协议...

    Microsoft.Web.Services2.rar

    描述中提到的"Microsoft.Web.Services2.Security.Tokens.UsernameToken",这是微软Web服务库中的一个安全模块,涉及到SOAP安全令牌,特别是用户名令牌(UsernameToken)。在Web服务的安全认证中,UsernameToken是一...

    net调用javawebservie

    本文主要介绍如何使用.NET(C#)通过WSE3.0来调用Java Web服务,特别是在WSI(Web Services Interoperability)协议的UserNameToken验证机制下的调用方式。 1. **WSE3.0(Web Services Enhancements)**: WSE是...

    CXF 通过用户名和密码进行验证

    Apache CXF是一个开源的Java框架,它用于创建和消费SOAP和RESTful Web服务。这里的验证过程通常涉及到安全控制,确保只有经过授权的用户才能访问服务。 在Web服务中,认证是确保用户身份的过程,而授权则是决定用户...

    onvif 1.02 c/c++源代码,有简单使用说明,特别加入了onvif 权限(wsse)认证实现说明

    标题中的"onvif 1.02"指的是ONVIF...使用时,需理解SOAP协议,熟悉WS-Security的Usernametoken认证,并遵循提供的使用说明。同时,gSOAP库的使用也是关键,它简化了SOAP消息的构建和处理,以及WS-Security的集成。

    Web Service SOAP Client set SOAP Header

    SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse"); usernameToken.addAttribute(new QName(...

    IBM WebSphere 开发者技术期刊: 通过 WebSphe…

    【描述】:虽然原始描述为空,但可以推测这篇博客文章可能详细阐述了WebSphere中的安全性,包括如何使用UsernameToken进行用户身份验证,以及如何配置权限和角色以实现不同级别的访问控制。 【标签】:“源码”、...

    【尚硅谷】徐靖博 最新电商项目实战(完结)

    8 I7 X) ^ 98.05 cxf框架的usernametoken安全拦截器 99.06 cxf客户端加入安全拦截( L+ {$ q; @" j" N e 100.07 订单和结算的总体流程( U# O4 ^: y0 h" Y7 W 101.08 订单拆单的介绍_视频补充' Q( R9 W9 g4 ]/ X6 b% B...

    WebService之XFire和Jax实现身份验证

    例如,可以使用XFire的WS-Security支持,结合UsernameToken或X509证书来进行用户身份验证。UsernameToken方式通常涉及到用户名和密码的传递,而X509证书则基于公钥基础设施(PKI),使用数字证书进行身份验证。为了...

    ws 加验证消息头

    例如,可以使用`&lt;wsse:Security&gt;`元素来包含认证信息,如用户名令牌(UsernameToken)、X.509证书或 Kerberos 令牌。 对于"简单易懂"的描述,这可能意味着我们将探讨一种相对基础的验证方法,如...

    WSE3.0学习实例

    根据学习资料,自己开发的两个WSE3.0的学习实例:UsernameToken和X509Assertion,希望对大家有帮助。 注:在这里我将客户端和Web服务端份非别开发,所以有四个工程文件。 注2:最重要的是证书的位置!一定要配置好。...

    SOAPHEADER方法增强WebService安全性代码

    SOAPElement usernameToken = security.addChildElement("UsernameToken"); usernameToken.addChildElement("Username").addTextNode("myUsername"); usernameToken.addChildElement("Password").addTextNode(...

    Cxf客户端及服务器端,实现客户端和服务器端的权限验证

    在本文中,我们将深入探讨如何在Apache CXF框架中实现客户端和服务器端的权限验证。...希望这个简要介绍能帮助你在研究CXF权限验证时找到方向。如果你需要更详细的信息,可以查阅CXF的官方文档或社区资源。

    Spring+xFire+wss4j配置Helloworld完整版,Myeclipse项目服务端+客户端.rar

    &lt;property name="securementActions" value="UsernameToken"/&gt; ``` 客户端则需要配置相应的安全参数,以便能够成功调用服务。这通常涉及到设置认证信息和信任的证书,以便进行安全通信。 项目中包含的`...

    cxf与spring整合,以及webservice传输验证demo

    至此,我们已经创建了一个使用CXF和Spring集成的Web服务,同时实现了基于UsernameToken的传输验证。这个简单的例子展示了如何在实际项目中部署和调用Web服务,并添加安全层以确保通信的安全性。通过这种方式,开发者...

    webservice实例axis2框架下基于rampart安全认证的.pdf

    总结来说,文档详细介绍了如何在Axis2框架下实现基于Rampart的安全认证。首先,通过配置Axis2的目录结构和相关文件,我们能够为Web Services提供一个良好的运行环境。其次,通过在服务描述文件中设置安全相关的参数...

    CXF V3.2.4 实现的WebService调用(带安全认证)

    props.put("action", "UsernameToken"); props.put("user", "your_username"); props.put("passwordType", "PasswordText"); props.put("passwordCallbackClass", YourPasswordCallbackClass.class.getName()); ...

Global site tag (gtag.js) - Google Analytics