在WCF customBinding中接受UsernameToken和BinarySecurityToken

时间:2012-06-12 15:32:45

标签: wcf web-services ws-security

我正在使用customBinding端点构建一个WCF Web服务,并且我正在接受另一方发送给我的WS-Security标头。我们都遵循英国国家健康服务所制定的规范,因此我无法修改要求。

根据规范,<{1}}标题的基本结构应如下所示:

<wsse:Security>

在我的网络服务中,我尝试使用以下绑定:

<wsse:Security>
    <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurityutility-1.0.xsd" wsu:Id="6CCF6A2B-11A6-11DF-86D1-236A99759561" >
        <wsu:Created>2012-06-12T09:00:00Z</wsu:Created>
        <wsu:Expires>2012-06-12T09:15:00Z</wsu:Expires>
    </wsu:Timestamp>
    <wsse:UsernameToken>
        <wsse:Username>SomeUsername</wsse:Username>
    </wsse:UsernameToken>
    <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wsssoap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="30b91ede-35c2-11df-aac9-97f155153931 ">xxx...</wsse:BinarySecurityToken>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#RSA-SHA1" />
            <Reference URI="#6CCF6A2B-11A6-11DF-86D1-236A99759561" />
            <Transforms>
                <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>xxx...</DigestValue>
        </SignedInfo>
        <SignatureValue>xxx...</SignatureValue>
        <KeyInfo>
            <wsse:SecurityTokenReference>
                <wsse:Reference URI="#30b91ede-35c2-11df-aac9-97f155153931 "/>
            </wsse:SecurityTokenReference>
        </KeyInfo>
    </Signature>
</wsse:Security>

(我使用customBinding的原因是我必须同时支持 WS-Addressing WS-Security 而不是 SOAP 1.1 ,以及接受了this answer的建议。)

如果我通过Fiddler运行示例请求,我的WCF跟踪中出现以下错误:

  

无法找到令牌身份验证器   ' System.IdentityModel.Tokens.UserNameSecurityToken '令牌类型。令牌   根据当前的安全性,不能接受该类型的   设置。

我认为这是因为它无法验证<customBinding> <binding name="wsHttpSoap11" > <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" /> <security authenticationMode="MutualCertificate"> </security> <httpTransport/> </binding> </customBinding> 。如果我将绑定安全性更改为:

<UsernameToken>

然后我收到此错误:

  

无法找到令牌身份验证器   ' System.IdentityModel.Tokens.X509SecurityToken '令牌类型。令牌   根据当前的安全设置,无法接受该类型。

我相信这是因为它现在无法验证<security authenticationMode="UserNameForCertificate">

因此,问题是:

  1. 我的假设是否正确错误消息的原因 (它只能在当前配置中处理一个令牌)?
  2. 如何配置它以接受两个令牌?
  3. 更新

    感谢@Yaron我现在添加了一个自定义绑定扩展, UserNameSecurityToken X509SecurityToken 正在验证。

    但是现在它在验证XML签名的阶段失败了。 HTTP响应中返回的异常是:

      

    邮件安全验证失败。

    如果我深入研究服务跟踪查看器中的堆栈跟踪,我会看到:

      

    ... System.Security.Cryptography.CryptographicException

         

    签名验证失败。

         

    在System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash,   AsymmetricSignatureDeformatter deformatter)   在System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)...

    任何人都可以帮我弄清楚为什么会这样吗?我此刻迷失了。我尝试使用some sample code尝试手动验证签名,但它表示签名无效。在回到供应商之前,我怎么能确定它是否存在?这是应该有效的吗?我们应该在线路的某个地方分享一些证书吗?

1 个答案:

答案 0 :(得分:4)

您需要从代码创建绑定。

        var b = new CustomBinding();
        var sec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);
        sec.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
        sec.MessageSecurityVersion =
            MessageSecurityVersion.
                WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
        sec.IncludeTimestamp = true;
        sec.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.EncryptBeforeSign;

        b.Elements.Add(sec);
        b.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
        b.Elements.Add(new HttpTransportBindingElement());

(由于我无法通过您的帖子告诉您使用哪种肥皂版本或是否应用了ssl,因此估算了一些值)

另一个问题,你可能运行得太晚,你需要在ServiceContract属性上使用ProtectionLevel.SignOnly,但这与此问题无关。