WCF - 如何调试“签名验证失败”消息

时间:2013-01-21 17:47:09

标签: c# wcf soap wcf-security wss4j

我创建了一个调用Spring Web Services 2.1.0 + Apache WSS4J 1.6.7(WS-Sec 1.1)服务器并返回响应的WCF客户端。

WCF抱怨“邮件安全验证失败”,{{1>} “签名验证失败”

问题是,我没有其他方法可以调试它,因为它在生产服务器上。我有WCF记录SOAP进出的情况以及抛出的异常,运行服务器的人说他们可以在他们的结尾处理好反应(即他们在验证签名时没有问题)

有关如何进一步调试的想法吗?我是否可以创建一个控制台应用程序来验证SOAP?

我已经能够将请求发送到他们的服务器了并且我得到了回复所以我一直试图通过控制台应用程序验证这一点,以便我可以看到响应出错的地方,但是无法获得控制台应用程序验证XML - 当我运行请求和响应时,CheckSignature总是返回false。

注意:我已尝试将InnerException设为xmlDoc.PreserveWhitespacetrue

任何帮助都表示赞赏

还要注意 - 下面的代码只是我放在一起测试签名的东西。实际的服务绑定/服务客户端是一个单独的应用程序。对此的绑定如下:

false

从代码绑定 - 检索并修改配置XML绑定

<customBinding>
        <binding name="MY_BINDING">
          <transactionFlow/>
          <security defaultAlgorithmSuite="Basic256Rsa15" authenticationMode="MutualCertificate"
                    messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
                    requireDerivedKeys="false" messageProtectionOrder="SignBeforeEncrypt" 
                    allowSerializedSigningTokenOnReply="true" securityHeaderLayout="Lax" >
            <secureConversationBootstrap authenticationMode="CertificateOverTransport"
                                         messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                                         requireDerivedKeys="false" />
          </security>
          <textMessageEncoding messageVersion="Soap11WSAddressing10"/>
          <httpsTransport requireClientCertificate="true"/>
        </binding>
      </customBinding>

此应用程序仅用于检查我直接在SOAP信封中提供的签名,希望调试签名并查看失败的内容

public static CustomBinding GetServiceBinding()
        {            
            //Get custom binding reference from app.config
            CustomBinding binding = new CustomBinding(SettingsLookup.WcfCustomBindingName);
            binding.ReceiveTimeout = new TimeSpan(0, 0, 15, 0);
            binding.SendTimeout = new TimeSpan(0, 0, 15, 0);

            // Get the x509ProtectionParams from the security element
            X509SecurityTokenParameters tokenParameters = new X509SecurityTokenParameters();
            tokenParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
            tokenParameters.RequireDerivedKeys = false;
            tokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;

            // Reference the asymettric security element            
            AsymmetricSecurityBindingElement securityBindingElement = binding.Elements.Find<AsymmetricSecurityBindingElement>();
            // Set the X509SecurityTokenParameters to point to the one's just configured. This is for symetric encryption, for asymetric this line needs to change
            //securityBindingElement.ProtectionTokenParameters = tokenParameters;
            securityBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
            securityBindingElement.InitiatorTokenParameters = tokenParameters;
            securityBindingElement.LocalClientSettings.DetectReplays = false;
            securityBindingElement.RequireSignatureConfirmation = true;
            //Set timestamp to false as it's not in the VHI request
            securityBindingElement.IncludeTimestamp = true;
            securityBindingElement.LocalClientSettings.TimestampValidityDuration = new TimeSpan(12,0,0);




            return binding;
        }

例外

// TEST PROGRAM JUST FOR CHECKING SIGNATURE, CONSOLE APP SEPERATE FROM MAIN APP
class Program
        {
            static void Main(string[] args)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.PreserveWhitespace = true;
                xmlDoc.LoadXml(Resource1.request);

                X509Certificate2 cert = new X509Certificate2(@"D:\TEMP\certs\pub_and_private_key.pfx", "password");

                bool result = ValidateSoapBodySignature(xmlDoc, cert);

            }

        public static bool ValidateSoapBodySignature(XmlDocument doc, X509Certificate2 cert)
        {
            // *** Load the doc this time
            SignedXmlWithId sdoc = new SignedXmlWithId(doc);

            // *** Find the signature and load it into SignedXml
            XmlNodeList nodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
            sdoc.LoadXml((XmlElement)nodeList[0]);

            // *** Now read the actual signature and validate
            bool result = sdoc.CheckSignature(cert, true);

            return result;
        }


    }

    public class SignedXmlWithId : SignedXml
    {
        public SignedXmlWithId(XmlDocument xml)
            : base(xml)
        {
        }

        public SignedXmlWithId(XmlElement xmlElement)
            : base(xmlElement)
        {
        }

        public override XmlElement GetIdElement(XmlDocument doc, string id)
        {
            // check to see if it's a standard ID reference
            XmlElement idElem = base.GetIdElement(doc, id);

            if (idElem == null)
            {
                XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                nsManager.AddNamespace("u", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

                idElem = doc.SelectSingleNode("//*[@u:Id=\"" + id + "\"]", nsManager) as XmlElement;
            }

            return idElem;
        }
    }

SOAP

System.ServiceModel.Security.MessageSecurityException: Message security verification failed. 

---&amp;gt; System.Security.Cryptography.CryptographicException: The signature verification failed.
   at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
   at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
   at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
   at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
   at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp;amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp;amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   --- End of inner exception stack trace ---</ExceptionString><InnerException><ExceptionType>System.Security.Cryptography.CryptographicException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The signature verification failed.</Message><StackTrace>   at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
   at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
   at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
   at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
   at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp;amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp;amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)</StackTrace><ExceptionString>System.Security.Cryptography.CryptographicException: The signature verification failed.
   at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
   at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
   at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
   at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
   at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp;amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp;amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)

1 个答案:

答案 0 :(得分:0)

除了启用WCF安全跟踪之外,我还建议您调试.net框架代码。 要执行此操作,您必须按照此处所述配置VS:

http://referencesource.microsoft.com/setup.html

您还可以下载框架源代码,并根据wcf跟踪检查部分代码中发生异常的情况。