none
WCF security/policy 异常:{"Failed to assert identity with UsernameToken."} RRS feed

  • 问题

  • 开发环境:.net framewor4.0 , VS2010, C#
    下面是wsdl里安全策略部分:

    <?xml version="1.0" encoding="UTF-8"?>
    <WL5G3N1:definitions targetNamespace="http://mysample.com.cn/" xmlns:WL5G3N0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:WL5G3N1="http://schemas.xmlsoap.org/wsdl/" xmlns:WL5G3N2="http://mysample.com.cn/" xmlns:WL5G3N3="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
    <wsp:UsingPolicy WL5G3N1:Required="true" /> <wsp:Policy WL5G3N0:Id="WS-Policy-WSSE-PasswordDigest"> <wssp:Identity xmlns:wssp="http://www.bea.com/wls90/security/policy"> <wssp:SupportedTokens> <wssp:SecurityToken TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken"> <wssp:UsePassword Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest" /> </wssp:SecurityToken> </wssp:SupportedTokens> </wssp:Identity>
    <WL5G3N1:types> ...</WL5G3N1:types>
    <WL5G3N1:message name="ValidateNewRegistrationOrderRequest"> ...</WL5G3N1:message>
    <WL5G3N1:message name="ValidateNewRegistrationOrderResponse"> ...</WL5G3N1:message>
    <WL5G3N1:portType name="ValidateNewRegistrationOrder"> ... </WL5G3N1:portType>
    <WL5G3N1:binding name="ValidateNewRegistrationOrderHTTP" type="WL5G3N2:ValidateNewRegistrationOrder">
        <WL5G3N3:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <WL5G3N1:operation name="ValidateNewRegistrationOrder">
          <WL5G3N3:operation soapAction="urn:#ValidateNewRegistrationOrderOperation"/>
          <WL5G3N1:input>
            <wsp:Policy>
              <wsp:PolicyReference URI="#WS-Policy-WSSE-PasswordDigest"/>
            </wsp:Policy>
    ......
    </WL5G3N1:input>
          <WL5G3N1:output>
            ......
    </WL5G3N1:output>
        </WL5G3N1:operation>
      </WL5G3N1:binding>
      <WL5G3N1:service name="ValidateNewRegistrationOrder">
        <WL5G3N1:port binding="WL5G3N2:ValidateNewRegistrationOrderHTTP" name="ValidateNewRegistrationOrder">
          <WL5G3N3:address location="http://mysample:8080/ValidateNewRegistrationOrder/v1.0"/>
        </WL5G3N1:port>
      </WL5G3N1:service>
    </WL5G3N1:definitions>





    仿照下面的链接,我写了 CustomCredentials类,并完成 PasswordDigest 类型 的Usernametoken 。

    http://stackoverflow.com/questions/896901/wcf-adding-nonce-to-usernametoken/20325151#20325151

    具体代码如下:

    public static ValidateNewRegistrationOrderClient CreateProxy(string url, string username, string password)
            {
    
                CustomBinding binding = new CustomBinding();
                TransportSecurityBindingElement security = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
                security.IncludeTimestamp = false;
                security.AllowInsecureTransport = true;
                security.EnableUnsecuredResponse = true;
                security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;           
    
                TextMessageEncodingBindingElement encoding = new TextMessageEncodingBindingElement();
                encoding.MessageVersion = MessageVersion.Soap11WSAddressing10;
    
                HttpTransportBindingElement transport = new HttpTransportBindingElement();                    
    
                binding.Elements.Add(security);
                binding.Elements.Add(encoding);
                binding.Elements.Add(transport);
    
                ValidateNewRegistrationOrderClient client = new ValidateNewRegistrationOrderClient(binding,
                    new EndpointAddress(url));
    
                client.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
                client.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials()); 
    
                client.ClientCredentials.UserName.UserName = username;
                client.ClientCredentials.UserName.Password = password;
    
                return client;
            }

    最终得到的请求报文头如下:

    <s:Header>
      <a:Action> ... </a:Action>
      <a:MessageID> ...</a:MessageID>
      <a:ReplyTo> ... </a:ReplyTo>
      <a:To> ... </a:To>
      <o:Security  
         s:mustUnderstand="1"  
         xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">  
         <o:UsernameToken  
            u:Id="uuid-3ef12f9d-75ab-407f-abe0-f833d063ac5b-1"  
            xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <o:Username>MyUserName</o:Username>
            <o:Password  
               Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">  
               EncryptedPassword
            </o:password>
            <o:Nonce  
               EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">  
               StringWith28Chars  
            </o:Nonce>
            <u:Created>2013-11-26T12:21:22.627Z</u:Created>
         </o:UsernameToken>
      </o:Security>
    </s:Header>
    我认为 Usernametoken 密码类型 Digest 还算是正确的。
    但是:
    1. 理论上,Nonce是唯一的随机数,网页上搜到的例子基本全都是24位 且 以双等号==结尾。
       而我的 Nonce 和 Password 长度都是 28 字符。不知道这是否有影响?

    2. 重点问题在 Identity , http://www.bea.com/wls90/security/policy 是 weblogicserver 的东西,只用于java的。
       微软在 .net framework 4.5 里,对 ClientCredential 增加了 Identity 属性,
       但我目前是 4.0 , 而且也不确定 4.5里的identity 是否就是我想解决的Identity.

    3. 曾经也想尝试 不添加服务引用,而是直接 HttpWebRequest , 但也没完全想清楚......

    希望大家给予建议和帮助,不胜感激额!


    2013年12月3日 8:25

答案

  • DroidXgnaW 你好:
    首先,谢谢您的回复。

    我补充完整了几乎整个WSDL文件,并没有提到 关于 该 Token 的其他任何信息 。
    现在拥有的内容:服务地址 (自然就有WSDL),UserName , Passowrd 。
    我又该怎么去应用 SAML Token 呢?
    盼复。

    看下 WCF 中 Claims-Based Authorization 的相关资料。

    http://msdn.microsoft.com/zh-cn/library/aa355062(v=vs.100).aspx

    上面是 4.5 之前的做法,4.5 以后,可以看下 Claims-aware WCF 的相关资料。

    2013年12月5日 1:31

全部回复

  • 你这个看上去很应该是 SAML Token 。

    windows identity foundation 就是干这事的。

    在 4.5 之前,是单独的程序集,后来加入到 4.5 中了,应该是 System.IdentityModel。

    2013年12月3日 8:37
  • DroidXgnaW 你好:
    首先,谢谢您的回复。

    我补充完整了几乎整个WSDL文件,并没有提到 关于 该 Token 的其他任何信息 。
    现在拥有的内容:服务地址 (自然就有WSDL),UserName , Passowrd 。
    我又该怎么去应用 SAML Token 呢?
    盼复。

    2013年12月4日 12:11
  • DroidXgnaW 你好:
    首先,谢谢您的回复。

    我补充完整了几乎整个WSDL文件,并没有提到 关于 该 Token 的其他任何信息 。
    现在拥有的内容:服务地址 (自然就有WSDL),UserName , Passowrd 。
    我又该怎么去应用 SAML Token 呢?
    盼复。

    看下 WCF 中 Claims-Based Authorization 的相关资料。

    http://msdn.microsoft.com/zh-cn/library/aa355062(v=vs.100).aspx

    上面是 4.5 之前的做法,4.5 以后,可以看下 Claims-aware WCF 的相关资料。

    2013年12月5日 1:31