本文介绍了绑定产生 2 个安全标签,带有 2 个 X509's+ usernmaetoken 和 nonce 的soap xml的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用这个博客来实现随机数,密码文本.http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/我看过很多其他的博客,但我想尝试一下.

I am using this blog to implement nonce, password text.http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/I've seen many other blogs with do but i would like to try this out.

这是我目前所做的首先让我说,我无法控制服务.我只是消费者.

This is what I have done so farLet me first say, I have no control over the service. I am just the consumer.

passwordtextmessaginspector 实现了 IClientMessageInspector,它允许我们修改传出的消息.在这种情况下,我想将 usernametoken 添加到包含 nonce 的消息中.所以 Ben 在 BeforeRequestSent 中使用了 WSE.使用系统;

passwordtextmessaginspector implements IClientMessageInspector which lets us modify the outgoing message. In this case, I would like to add usernametoken to the message including nonce. So Ben uses WSE in the BeforeRequestSent. using System;

    public class PasswordTextMessageInspector : IClientMessageInspector
    {
        public string Username { get; set; }
        public string Password { get; set; }

        public PasswordTextMessageInspector(string username, string password)
        {
            this.Username = username;
            this.Password = password;
        }

        #region IClientMessageInspector Members

        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            throw new NotImplementedException();
        }

        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
            // Use the WSE 3.0 security token class
            UsernameToken token = new UsernameToken(this.Username, this.Password, PasswordOption.SendPlainText);

            // Serialize the token to XML
            XmlElement securityToken = token.GetXml(new XmlDocument());

            //
            MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityToken, false);
            request.Headers.Add(securityHeader);

            // complete
            return Convert.DBNull;
        }

这是自定义行为

    public class PasswordTextBehavior : IEndpointBehavior
    {

        public string Username { get; set; }
        public string Password { get; set; }

        public PasswordTextBehavior(string username, string password)
        {
            this.Username = username;
            this.Password = password;
        }

        #region IEndpointBehavior Members

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            throw new NotImplementedException();


        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new PasswordTextMessageInspector(this.Username, this.Password));
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            throw new NotImplementedException();
        }

        public void Validate(ServiceEndpoint endpoint)
        {
           throw new NotImplementedException();
        }

        #endregion
    }
}

我的 soap 请求已经有 2 个 x509 证书.我只是在发送之前用随机数添加这个用户名令牌.这就是我的代理客户端的样子

My soap request already has 2 x509certificates. I am just adding this usernametoken with nonce before sending it. This is how my proxyclient looks like

   private ProxyGeneration.MHSClient GetProxy()
        {

            ProxyGeneration.MHSClient proxy = new ProxyGeneration.MHSClient(GetCustomBinding(), new EndpointAddress(new Uri("https://service100.emedny.org:9047/MHService"), EndpointIdentity.CreateDnsIdentity("SEREVR"), new AddressHeaderCollection()));

    var vs = proxy.Endpoint.Behaviors.Where((i) => i.GetType().Namespace.Contains("VisualStudio"));
    proxy.Endpoint.Behaviors.Remove((System.ServiceModel.Description.IEndpointBehavior)vs.Single());
    proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName,"USER");
    proxy.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "SERVER");
    PasswordTextBehavior behavior = new PasswordTextBehavior("USER", "PWD");
    proxy.Endpoint.Behaviors.Add(behavior);

   proxy.ClientCredentials.UserName.UserName = "USER";
   proxy.ClientCredentials.UserName.Password = "PWD";

    return proxy;
        }

private CustomBinding GetCustomBinding()
{


    AsymmetricSecurityBindingElement secBE = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement
        (
        MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10
        );
    secBE.ProtectTokens = false;
    X509SecurityTokenParameters x509ProtectionParameters = new X509SecurityTokenParameters();
    x509ProtectionParameters.RequireDerivedKeys = false;
    x509ProtectionParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.SubjectKeyIdentifier;
    x509ProtectionParameters.ReferenceStyle = SecurityTokenReferenceStyle.Internal;

    //x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
    secBE.MessageSecurityVersion = System.ServiceModel.MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
    secBE.InitiatorTokenParameters = x509ProtectionParameters;
    secBE.RecipientTokenParameters = x509ProtectionParameters;
    secBE.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;

    secBE.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
    secBE.EnableUnsecuredResponse = true;
    secBE.SetKeyDerivation(false);
    secBE.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesRsa15;
    secBE.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
    secBE.ProtectTokens = true;
    //  secBE.in = SecurityTokenInclusionMode.Never, RequireDerivedKeys = false );
    secBE.EnableUnsecuredResponse = true;
    secBE.IncludeTimestamp = false;

    TextMessageEncodingBindingElement textEncBE = new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, System.Text.Encoding.UTF8);
    HttpsTransportBindingElement httpsBE = new HttpsTransportBindingElement();
    httpsBE.RequireClientCertificate = true;

    CustomBinding myBinding = new CustomBinding();
    myBinding.Elements.Add(secBE);
    myBinding.Elements.Add(textEncBE);
    myBinding.Elements.Add(httpsBE);
    return myBinding;
}

所以我添加了一个新的行为 PasswordTextBehavior proxy.endpoint.behavior.add(passwordtextbehavior).

So I am adding a new Behavior PasswordTextBehavior proxy.endpoint.behavior.add(passwordtextbehavior).

这是一种有效的方法吗?我得到了两个安全部分.

Is this a valid way to do this. I am getting two security sections.

我的标题

  <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
 <wsse:UsernameToken wsu:Id="SecurityToken-ec50def9-1c3b-476a-9bcc-2af556e5e0e7" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username><!--Removed--></wsse:Username><wsse:Password><!--Removed-->
 </wsse:Password><wsse:Nonce><!--Removed--></wsse:Nonce><wsu:Created>2013-05-28T14:56:46Z</wsu:Created></wsse:UsernameToken>
 </Security>
<a:To s:mustUnderstand="1" u:Id="_6">https://service100.emedny.org:9047/MHService</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:BinarySecurityToken><!--Removed--></o:BinarySecurityToken>
     <o:BinarySecurityToken><!--Removed--></o:BinarySecurityToken>
     <e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#">

应该只有一个安全标签和一个必须理解.

There should be only one security tag and one mustunderstand.

供应商样本

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mhs="http://org/TEST/mhs/" xmlns:urn="urn:hl7-org:v3">
<soapenv:Header>
<wsse:Security soap:mustUnderstand="1" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:BinarySecurityToken ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-e00c8062-83d2-4f04-88fc-996218e7bb3d">MIICeDCC....(signed user MLS cert).......</wsse:BinarySecurityToken>
<wsse:BinarySecurityToken ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685">MIIDFj.....( MLS web-service end-point public cert)........</wsse:BinarySecurityToken>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-970e9a80-00cc-4c86-8ec4-3ba16e029a5b">
<wsse:Username>....your_username.....</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">.....your_plaintext_password....</wsse:Password>
<wsse:Nonce>KNyu6MsXCkTg4DDyvwvEiw==</wsse:Nonce>
<wsu:Created>2010-09-15T18:00:30Z</wsu:Created>
</wsse:UsernameToken>
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference>
<wsse:Reference URI="#SecurityToken-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>gpBAWt91pdwhKva............</xenc:CipherValue>
</xenc:CipherData>
<xenc:ReferenceList>
<xenc:DataReference URI="#Enc-0641b860-b16d-4941-91c0-d60bece67794"/>
</xenc:ReferenceList>
</xenc:EncryptedKey>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>

<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#Id-f10674fd-b999-47c9-9568-c11fa5e5405b">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>wRUq.........</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>tBSsaZi........</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="#SecurityToken-e00c8062-83d2-4f04-88fc-996218e7bb3d" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</KeyInfo>
</Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body wsu:Id="Id-f10674fd-b999-47c9-9568-c11fa5e5405b" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<xenc:EncryptedData Id="Enc-0641b860-b16d-4941-91c0-d60bece67794" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
<xenc:CipherData>
<xenc:CipherValue>SQsTCAK6ZaVhojB8+Y.........</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soapenv:Body>
</soapenv:Envelope>

推荐答案

您显然已经启动并运行了 WCF 跟踪,这是跟踪此类问题的最佳方法.

You obviously have WCF tracing up and running, which is the bext way to track down problems like this.

您现在需要一个预期消息输出的示例.从此你可以开始有条不紊地向后工作.

You now need an example of the expected message output. From that you can start to work methodically backwards.

您需要建立签名,然后使用证书.如果需要,您可以使用 WSE 类 来简化您的开发,就像我支持基本配置文件一样.

You need to build up the signature then using the certificate. If you want, you could use the WSE classes to shortcut your development, in the same I did to support the basic profile.

您可能需要创建一个自定义 BinarySecurityToken.标准 BinarySecurityToken 类扩展安全令牌.

You might have to create a custom BinarySecurityToken. The standard BinarySecurityToken class extends SecurityToken.

关于 WCF 中的 BinarySecuritytoken 支持,有许多 StackOverflow 问题可能会有所帮助:

With regards to BinarySecuritytoken support in WCF, there are a number of StackOverflow questions that might help:

  1. 在 WCF customBinding 中同时接受 UsernameToken 和 BinarySecurityToken
  2. 如何在soap消息中签署BinarySecurityToken
  3. http://threeisit.com/post/WCF2c-Interop2c-and-the-elusive-BinarySecurityToken.aspx

这篇关于绑定产生 2 个安全标签,带有 2 个 X509's+ usernmaetoken 和 nonce 的soap xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 23:41