绑定生成2个安全标签,soap xml与2 X509 + usernmaetoken与nonce

时间:2013-05-27 22:43:34

标签: wcf wcf-security ws-security

我正在使用此博客来实现nonce,密码文本。 http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/ 我见过许多其他博客,但我想尝试一下。

这是我到目前为止所做的 我先说,我无法控制服务。我只是消费者。

passwordtextmessaginspector实现IClientMessageInspector,它允许我们修改传出消息。在这种情况下,我想在包含nonce的消息中添加usernametoken。所以Ben在BeforeRequestSent中使用了WSE。         使用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
    }
}

我的肥皂请求已经有2 x509证书。我只是在发送之前用nonce添加这个usernametoken。 这就是我的proxyclient的样子

   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;
}

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

这是一种有效的方法吗?我有两个安全部分。

我的标题

  <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#">

应该只有一个安全标签,一个必须理解。

供应商样本

<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>

1 个答案:

答案 0 :(得分:0)

你显然已经启动并运行了WCF,这是跟踪这类问题的bext方法。

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

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

您可能需要创建custom BinarySecurityToken。标准BinarySecurityToken类扩展了SecurityToken。

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

  1. Accepting both UsernameToken and BinarySecurityToken in WCF customBinding
  2. How do i sign a BinarySecurityToken in soap message
  3. http://threeisit.com/post/WCF2c-Interop2c-and-the-elusive-BinarySecurityToken.aspx