使用代码隐藏而不是 Web.Config 端点调用服务时出现不安全或安全错误错误

我有一个具有消息安全性的 WCF 服务,并且我正在尝试将客户端连接到它。


使用由 Visual Studio 中的“添加服务引用”自动生成的默认 Web.Config 设置,连接效果非常好,设置如下:


端点:


  <endpoint address="http://localhost:56017/services/MaternumPdfService.svc/soap"

    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMaternumPdfService"

    contract="MaternumPdfServiceReference.IMaternumPdfService" name="WSHttpBinding_IMaternumPdfService">

    <identity>

      <certificate encodedValue="BASE64 IS HERE" />

    </identity>

  </endpoint>

捆绑:


    <binding name="WSHttpBinding_IMaternumPdfService" maxReceivedMessageSize="2147483647">

      <security>

        <message clientCredentialType="UserName" negotiateServiceCredential="false"

          establishSecurityContext="false" />

      </security>

      <readerQuotas maxStringContentLength="2147483647" maxDepth="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>

    </binding>

这可以顺利进行:


        using (MaternumPdfServiceClient pdfService = new MaternumPdfServiceClient("WSHttpBinding_IMaternumPdfService"))

        {

            pdfService.ClientCredentials.UserName.UserName = "sample";

            pdfService.ClientCredentials.UserName.Password = "sample";

            pdfService.Open();


            if (!pdfService.State.Equals(CommunicationState.Opened))

            {

                return null;

            }


            MemoryStream ms = new MemoryStream();

            pdfService.GetMaternumPdf(pdftype,params).CopyTo(ms);

        }

我以为我正在 C# 版本和使用 Web.Config 设置的版本之间构建完全等效的代码,但与第二个版本连接会导致异常:

'An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.'

具有以下内部异常:

An error occurred when verifying security for the message.

不是特别清楚...这似乎与消息安全有关,但与 Web.Config 的连接工作得很好,这让我相信我没有在正确的类中设置证书。

我调查过:

WCF 给出不安全或不正确安全的故障错误

  • 服务器和客户端都是本地主机,所以不应该是时间不匹配

  • 凭据正确,因为 Web.Config 版本使用相同的凭据并且验证良好

  • 我使用的是 HTTP,而不是 HTTPS

  • 使用 IISExpress,而不是 IIS

就是这样。我认为我将客户端证书设置在错误的位置,如果不是通过 ClientCredentials.ClientCertificate.Certificate 或端点的身份,我应该如何设置它?


HUH函数
浏览 93回答 2
2回答

扬帆大鱼

...通常情况下,我的配置错误。我获得了一个名为“MaternumCertificateClient”的证书,而不是我的服务器配置的证书,即“MaternumCertificateServer”。更重要的是我是如何得出这个错误的。第一步,我设置 Wireshark 以查看服务器的回复内容:HTTP/1.1 500 Internal Server ErrorCache-Control: privateContent-Type: application/soap+xml; charset=utf-8Server: Microsoft-IIS/10.0Set-Cookie: ASP.NET_SessionId=k0xmopx3eitnvmocv1rjas4h; path=/; HttpOnlyX-AspNet-Version: 4.0.30319X-SourceFiles: =?UTF-8?B?QzpcREVWXE1BVFxNYXRlcm51bV9hcHBcc2VydmljZXNcTWF0ZXJudW1QZGZTZXJ2aWNlLnN2Y1xzb2Fw?=X-Powered-By: ASP.NETDate: Thu, 22 Aug 2019 16:25:19 GMTContent-Length: 648<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header>    <a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>    <a:RelatesTo>urn:uuid:uid is here</a:RelatesTo></s:Header><s:Body>    <s:Fault>        <s:Code>            <s:Value>s:Sender</s:Value>            <s:Subcode>                <s:Value xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</s:Value>            </s:Subcode>        </s:Code>        <s:Reason>            <s:Text xml:lang="en-GB">An error occurred when verifying security for the message.</s:Text>        </s:Reason>    </s:Fault></s:Body></s:Envelope>好不了多少,但我至少知道是谁抛出了异常。因此,正如所示,我使用以下内容设置我的服务器:<serviceSecurityAudit auditLogLocation=“Application“      serviceAuthorizationAuditLevel=“Failure“      messageAuthenticationAuditLevel=“Failure“      suppressAuditFailure=“true“ />在配置/system.serviceModel/behaviors/serviceBehaviors/behavior。然后,Windows 事件查看器会显示有关该错误的详细信息。显示的消息,MessageSecurityException: The EncryptedKey clause was not wrapped with the required encryption token 'System.IdentityModel.Tokens.X509SecurityToken'.表示证书不匹配。我正在加载一个名为 MaternumCertificateClient 的证书,并且我需要 MaternumCertificateServer。此外,这些行pdfService.ClientCredentials.ClientCertificate.Certificate = cert; pdfService.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust; pdfService.ClientCredentials.ServiceCertificate.DefaultCertificate = GetCertificate("MaternumCertificateClient");实际上并不需要;证书是从端点的身份中读取的,并且我的设置不需要这些设置即可工作。

德玛西亚99

正如您所指出的,除了我们使用证书对客户端进行身份验证之外,不需要在客户端提供证书。比如下面的配置。<wsHttpBinding>       <binding name="WSHttpBinding_ICalculator">         <security mode="Message">           <message clientCredentialType="Certificate" />         </security>       </binding>     </wsHttpBinding>在服务器端的绑定配置中,只有用户名/密码需要凭证。  <security>     <message clientCredentialType="UserName" negotiateServiceCredential="false"       establishSecurityContext="false" />   </security>证书通过使用公钥加密 SOAP 消息来提供消息安全性。在通信过程中,客户端和服务器端交换证书的公钥。我们甚至可以指定服务器域名作为身份,它只是用来保证服务器的身份。另外,如果你的回复解决了你的问题。请标记为有用,以便帮助遇到类似问题的其他人。如果有什么需要我帮忙的,请随时告诉我。
打开App,查看更多内容
随时随地看视频慕课网APP