WCF 客户端在证书验证中使用自登录时抛出 System.ServiceModel.Security.MessageSecurityException 错误

Posted

技术标签:

【中文标题】WCF 客户端在证书验证中使用自登录时抛出 System.ServiceModel.Security.MessageSecurityException 错误【英文标题】:WCF Client throws error of System.ServiceModel.Security.MessageSecurityException while using Self sign in Certificate Validation 【发布时间】:2021-09-13 03:51:23 【问题描述】:

我正在服务器端使用自签名证书验证 WCF 服务。当我在客户端使用它时,它会抛出一个错误

System.ServiceModel.Security.MessageSecurityException: '从另一方收到不安全或不正确安全的故障。有关故障代码和详细信息,请参阅内部 FaultException。 内部异常: FaultException:消息中至少有一个安全令牌无法验证。

对于开发,我在同一台机器上使用服务器和客户端。 WCF 服务(服务器)的 Web.Config 文件是:

<?xml version="1.0"?><configuration><appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8"/>
</system.web>
<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="WCF.MyServiceBehaviour">
                <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
                <serviceMetadata httpGetEnabled="true"/>
                <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="false"/>
                <serviceCredentials>
                    <serviceCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="8dbd4b4c95df218c448cc2992e9a5863d9a3d3ff" storeName ="My"/>
                </serviceCredentials>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service name="WCF.Service1" behaviorConfiguration="WCF.MyServiceBehaviour">
            <endpoint address=""
                                binding="basicHttpBinding"
                                contract="WCF.IService1"
                                bindingConfiguration="BasicHTTPEndPointBinding">
                <identity>
                    <dns value="tempSerCert"/>
                </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"   />
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:65300/service1.svc"/>
                </baseAddresses>
            </host>
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHTTPEndPointBinding">
                <security mode="Message">
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
    To browse web app root directory during debugging, set the value below to true.
    Set to false before deployment to avoid disclosing web app folder information.
  -->
    <directoryBrowse enabled="true"/>
</system.webServer>

客户端的 App.Config 是:

<?xml version="1.0" encoding="utf-8" ?><configuration>
<startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<system.serviceModel>
    <behaviors>
        <endpointBehaviors>
            <behavior name="CustomBehaviour" >
                <clientCredentials>
                    <clientCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="eaa8b0a5c5a84548984d562d4c795951e0badd59" storeName ="My"/>
                    <serviceCertificate>
                        <defaultCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="8dbd4b4c95df218c448cc2992e9a5863d9a3d3ff" storeName ="My"/>
                    </serviceCertificate> 
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1">
                <security mode="Message">
                    <message clientCredentialType="Certificate" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost/WCF/Service1.svc" behaviorConfiguration="CustomBehaviour" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="BasicHttpBinding_IService1" >
            <identity>
                <dns value="tempSerCert"/>
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

【问题讨论】:

我只使用默认模板来生成客户端上的 WCF 应用程序服务方法进行开发。 【参考方案1】:

自签名证书不具有权威性,您可以尝试在服务器web.config文件中设置certificateValidationMode=None来修复此错误。

【讨论】:

感谢您的回答..!你能否把这个声明自签名证书不权威更清楚一点。?你的意思是在开发阶段我应该设置certificateValidationMode=None,当我得到证书颁发机构提供的证书时,我会设置它现在的样子。? 关于自签名证书不权威:ssldragon.com/blog/self-signed-ssl-certificates-disadvantages

以上是关于WCF 客户端在证书验证中使用自登录时抛出 System.ServiceModel.Security.MessageSecurityException 错误的主要内容,如果未能解决你的问题,请参考以下文章

WCF 服务中的自定义客户端证书和用户名验证

WCF与相互身份验证

WCF Rest 自托管证书安全服务返回 401 未经授权

带有客户端证书身份验证的 Wcf 不适用于 soapui

通过 HTTPS 上的客户端证书对 WCF 请求进行身份验证

WCF 客户端证书验证 + Windows 身份验证