在WCF customBinding中接受UsernameToken和BinarySecurityToken

在WCF customBinding中接受UsernameToken和BinarySecurityToken,wcf,web-services,ws-security,Wcf,Web Services,Ws Security,我正在使用customBinding端点构建一个WCF web服务,并且在接受另一方发送给我的WS-Security头时遇到了困难。我们都遵循英国国家卫生服务局编写的规范,因此我无法修改要求 根据规范,收割台的基本结构应如下所示: <wsse:Security> <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurityutility-1.0.x

我正在使用customBinding端点构建一个WCF web服务,并且在接受另一方发送给我的WS-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>
在我的web服务中,我尝试使用以下绑定:

<customBinding>
    <binding name="wsHttpSoap11" >
        <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />
        <security authenticationMode="MutualCertificate">
        </security>
        <httpTransport/>
    </binding>
</customBinding>
我使用customBinding的原因是,我必须在SOAP1.1上支持WS-Addressing和WS-Security,并听取了他们的建议

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

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

我相信这是因为它无法验证。如果我将绑定安全性更改为:

<security authenticationMode="UserNameForCertificate">
然后我得到这个错误:

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

我相信这是因为它现在无法验证

因此,问题是:

关于错误消息的原因,我的假设是否正确 它在当前配置中只能处理一个令牌? 如何配置它以接受这两个令牌? 更新

多亏了@Yaron,我现在添加了一个自定义绑定扩展,UserNameSecurityToken和X509SecurityToken都在验证

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

消息安全验证失败

如果我在service trace viewer中深入研究堆栈跟踪,我会看到:

系统。安全。加密。加密异常

签名验证失败

在System.IdentityModel.SignedXml.VerifySignatureHash算法哈希中, 不对称设计格式化程序变形器 位于System.IdentityModel.SignedXml.StartSignatureReferenceSecurityKey验证密钥


有人能帮我弄清楚为什么会这样吗?我现在有点迷路了。我尝试使用尝试手动验证签名,但它表示签名无效。在我返回供应商之前,我如何确定它是否正确?这是不是应该起作用?我们应该在某个地方共享一些证书吗?

您需要从代码创建绑定

        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());
有些值是估计的,因为我无法通过您的帖子判断您使用的是哪个soap版本,或者是否应用了ssl


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

您需要从代码创建绑定

        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());
有些值是估计的,因为我无法通过您的帖子判断您使用的是哪个soap版本,或者是否应用了ssl


另一个问题是,您可能需要在ServiceContract属性上设置ProtectionLevel.SignOnly,但这与此问题无关。

非常感谢您的回答-我明天回到办公室后会尝试。在我的问题中,我确实提到我正在使用SOAP1.1,这对您的示例代码有影响吗?没有影响,但是如果我们也使用了寻址,这可能会有影响。如果您有任何问题,请发布完整的soap或将其发送给我。请查看我的更新,如有任何进一步的建议,将不胜感激。如果有用的话,很高兴向您发送完整的请求。wcf跟踪是否显示任何内部异常?它有时被隐藏在主。。。如果没有进一步的信息,那么使用完全相同的代码绑定构建一个wcf客户端来使用此服务。验证客户端是否工作,然后将其soap与实际接收的soap进行比较。哦,等等-看看示例soap,看起来只有soap主体被签名了?默认情况下,wcf还需要对用户名令牌和时间戳进行签名。这里面一定有什么例外。如果您将includeTimestamp设置为false,您可能不需要时间戳要求,但您需要对时间戳进行创造性处理。从发现内部异常开始,这样我们就可以得到一些反馈。在您发现错误后,还可以让我们知道是否使用了ssl。如果是这样的话,可能有一种方法可以使用CreateMutualCertificateBindingElement设置将其转换为传输绑定非常感谢您的回答-我明天回到办公室后会尝试这个方法。在我的问题中,我确实提到我正在使用SOAP1.1,这对您的示例代码有影响吗?没有影响,但是如果我们也使用了寻址,这可能会有影响。如果您有任何问题,请发布完整的so
ap或发送给我请查看我的更新,如有任何进一步的建议,将不胜感激。如果有用的话,很高兴向您发送完整的请求。wcf跟踪是否显示任何内部异常?它有时被隐藏在主。。。如果没有进一步的信息,那么使用完全相同的代码绑定构建一个wcf客户端来使用此服务。验证客户端是否工作,然后将其soap与实际接收的soap进行比较。哦,等等-看看示例soap,看起来只有soap主体被签名了?默认情况下,wcf还需要对用户名令牌和时间戳进行签名。这里面一定有什么例外。如果您将includeTimestamp设置为false,您可能不需要时间戳要求,但您需要对时间戳进行创造性处理。从发现内部异常开始,这样我们就可以得到一些反馈。在您发现错误后,还可以让我们知道是否使用了ssl。如果是这样,可能有一种方法可以使用CreateMutualCertificateBindingElement设置将其转换为传输绑定