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

Posted

技术标签:

【中文标题】WCF 给出不安全或不正确安全的故障错误【英文标题】:WCF gives an unsecured or incorrectly secured fault error 【发布时间】:2010-12-01 20:37:53 【问题描述】:

我正在尝试使用远程 svc Web 服务。我使用svcutil.exe 创建了代理类,之后我将该类添加到我的控制台应用程序中,但它会产生错误:

从另一方收到不安全的错误或不正确的安全故障。有关故障代码和详细信息,请参见内部故障异常。

System.ServiceModel.FaultException:验证消息安全性时出错

我没有创建 WCF 端,它是一个远程 svc。请帮忙。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="EloquaDataTransferService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Mtom" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://secure.eloqua.com/API/1.2/DataTransferService.svc"
                binding="basicHttpBinding" bindingConfiguration="EloquaDataTransferService"
                contract="DataTransferService" name="EloquaDataTransferService" />
        </client>
    </system.serviceModel>
</configuration>

这是我的app.config 文件。我使用obj.ServiceCredentials.UserName.UserName="xxxxxx".Password="xxxXx" 在我的consoleApp.cs 文件中提供用户名和密码

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <system.serviceModel>
      <bindings>
         <basicHttpBinding>
            <binding name="EloquaDataTransferService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
               <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
               <security mode="TransportWithMessageCredential">
                  <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
                  <message clientCredentialType="UserName" algorithmSuite="Default" />
               </security>
            </binding>
         </basicHttpBinding>
      </bindings>
      <client>
         <endpoint address="https://secure.eloqua.com/API/1.2/DataTransferService.svc" binding="basicHttpBinding" bindingConfiguration="EloquaDataTransferService" contract="DataTransferService" name="EloquaDataTransferService" />
      </client>
   </system.serviceModel>
</configuration>

【问题讨论】:

这是第一次访问服务时发生还是一段时间后发生? 如果没有更多细节就很难判断,但听起来远程服务正在等待未提供的凭据或身份验证。 【参考方案1】:

这是 WCF 服务抛出的一个非常隐蔽的错误。问题是 WCF 无法验证传递给服务的消息的安全性。

这几乎总是因为服务器时间偏差。远程服务器和客户端的系统时间必须在(通常)10 分钟内。否则,安全验证将失败。

我会致电 eloqua.com,了解他们的服务器时间,并将其与您的服务器时间进行比较。

【讨论】:

@user782534 如果您使用custom binding,您可以在配置中设置偏斜,但据我所知,您无法使用默认绑定。我也不知道完全禁用检查的能力。我倾向于反对那个。 我正在调用远程服务,比我的时间晚 9 小时内回复我。(事实上,在 SoapUI 日志上似乎是这样。)然后我收到了这个错误。响应标头包含我的发送日期,但在 SOAP UI 日志中,我注意到响应时间总是比我的请求时间长 9 小时。怎么会这样?即使我更改了本地日期时间。谢谢 @DavutGürbüz 可能是由于服务器的时间错误。如果客户端和服务器似乎都设置为相同的时间,我会检查一台或两台计算机上的时区设置——他们可能认为自己处于两个不同的时区,但显示的时间相同. 解决了我的问题。我的客户离服务器只有 1 分钟(!!!)。似乎 WCF 认为在很长的时间间隔后收到的消息是可疑的。 @Randolpho...hmmm...在我的情况下,我正在运行我的 WCF 服务、测试服务器和测试客户端都在同一台机器上运行,所以我不确定我的情况下,这可能是服务器时间偏差...如果您能告诉我其他情况...或者我能做些什么来解决这个问题,我将非常感激!【参考方案2】:

虽然您的问题已通过上述解决方案之一解决,但为了其他人的利益,这里有另一种选择。

当不正确的凭据传递到到使用用户名消息凭据的基本端点 (SOAP 1.1) 时,您也可能会遇到此异常。例如,如果您从代码调用服务并执行以下操作:

var service = new TestService();

service.ClientCredentials.UserName.UserName = "InvalidUser";
service.ClientCredentials.UserName.Password = "InvalidPass";

这与在传递无效凭据时抛出AccessDeniedException 的 WSHTTP 端点 (SOAP 1.2) 不同。我个人认为此处包含的消息有点误导(因为这个原因,我第一次遇到它时肯定花了我几分钟的时间),但是一旦我查阅了 WCF 诊断跟踪日志,根本原因就很清楚了。

【讨论】:

【参考方案3】:

您的 WCF 安全子系统显然存在问题。你用的是什么绑定?什么认证?加密?签约?你必须跨越域边界吗?

稍加检查进一步表明,如果客户端和服务器的时钟不同步(超过大约五分钟),其他人会遇到此错误,因为某些安全模式依赖于同步时钟。

【讨论】:

感谢您的回复!请检查我的 app.config 文件以及如何与服务器时钟同步?我只有远程服务器的 .svc 链接。 只要确保您的机器设置了正确的日期和时间。 在我的情况下,服务和客户端都在同一台机器上,但我仍然遇到异常。这会在某个时间(即 10 分钟)后发生,并且 clientCredentialType 是 Windows【参考方案4】:

我面临的同样问题是我的客户端应用程序是 WinForms 应用程序 C# 4.0

当我在这里阅读解决方案时,我检查了客户端计算机的日期和时间,但这是正确的,并且显示了当前时间,但我仍然面临这些问题。

经过一些变通,我发现选择了错误的时区,我在印度,时区是加拿大,主机服务器位于科威特。

我发现系统会将时间转换为世界时。

当我将时区更改为印度时区时,问题就解决了。

【讨论】:

这似乎不重要,但实际上它可能是问题的唯一解决方案:) 详细信息!【参考方案5】:

尝试将您的安全模式更改为“传输”。

安全标签和传输标签不匹配。

【讨论】:

【参考方案6】:

如果您从客户端传递用户凭据(根据下面的代码块),那么它应该与服务器上的用户名/密码匹配。否则你会得到这个错误。

仅供参考,在我的情况下,我使用“basicHTTPAuthentication”和“TransportWithMessageCredential”安全模式。 WCF 服务托管在 https 上的 IIS 中。

var service = new TestService();

service.ClientCredentials.UserName.UserName = "InvalidUser";
service.ClientCredentials.UserName.Password = "InvalidPass";

希望这对某人有所帮助... :)

【讨论】:

它帮助了我!该错误消息并未表明我可能发送了错误的凭据,并且我无权访问服务代码,因此我束手无策。我仔细检查了一下,果然,我发错了名字。现在我可以成功使用服务方法了。 这难道不归结为完全 the answer by @Xcalibur(2 年前给出,使用完全相同的代码 sn-p)?【参考方案7】:

这种异常多半发生在服务器出现错误的时候,最常见的就是认证数据库配置错误,或者认证。在我的情况下,有不同的时钟同步 确保客户端和服务器具有相同的设置

点击右下角的时间 -> “更改日期时间设置...” -> “互联网时间”选项卡 -> 更改设置... -> 选中“与互联网时间服务器同步”选项如果未选中 -> 从服务器下拉列表中选择“times.windows.com” -> 立即更新 -> 确定

【讨论】:

【参考方案8】:

对于它的价值 - 我也有这个错误,发现它是由 web 服务 web.config 中的连接字符串设置为连接到错误的机器引起的。

【讨论】:

这意味着用户名验证失败。 Xcalibur 在他的 [ans] (***.com/a/7280782/1977871) 中提到的东西【参考方案9】:

在我的例子中,我使用证书进行身份验证,certificateValidationMode 设置为“PeerTrust”,我忘记在 Windows 商店 (LocalMachine\TrustedPeople) 中安装客户端证书以使其被服务器接受。

【讨论】:

欢迎来到 Stack Overflow!目前尚不清楚您是在建议问题的解决方案还是说您有同样的问题。如果它是一个解决方案,您能否明确说明该解决方案的工作原理? @SuperBiasedMan 我认为实际上很清楚。他说“我正在使用……”和“我忘记了……”。可以理解,当他记得安装时问题就解决了,因此他建议做同样的事情“在 Windows 商店中安装客户端证书......以使其被服务器接受。” 我遇到了同样的问题(但就我而言,我已经在 LocalMachine\Personal 上安装了证书)。我也觉得很清楚,但是如果您需要更详细的说明,请点击此处: 1. 在 Windows 资源管理器中,只需右键单击证书文件,选择“安装证书”。 2. 选择“本地机器”,然后单击下一步 3. 选择“将所有证书放入以下存储” 4. 单击浏览 5. 选择适当的位置(对我来说是个人),然后按确定 6. 按下一步,完成 【参考方案10】:

就我而言,当我将 wshttpbinding 协议从 https 更改为 http 时,它开始工作了。

【讨论】:

【参考方案11】:

即使服务器和客户端在同一台机器上,我也遇到过过期服务引用的问题。如果这是问题,运行“更​​新服务参考”通常会解决它。

【讨论】:

【参考方案12】:

就我而言,在我的测试客户端-服务器应用程序中,我在同一台机器上遇到了这个错误。但是这个问题已经被“更新服务参考”解决了。

Tushar G. Walavalkar

【讨论】:

【参考方案13】:

只是为了分享...我有一个罕见的案例让我挠了几分钟后脑勺。即使时间偏差解决方案非常准确,而且我之前解决了这个问题,但这次不同。我在一台新的 Win8.1 机器上,我记得有一个时区问题,我手动调整了时间。好吧,尽管服务器和客户端显示的时间仅以秒为单位,但我一直收到错误消息。我所做的是在“日期和时间设置”中激活“夏季节省选项”(注意我确实处于夏季节省时间,但手动设置时间)然后进入互联网时间部分并刷新......时间在我的电脑保持不变,但错误消失了。

希望这对任何人都有用!

【讨论】:

【参考方案14】:

在我的例子中,这是 IIS 应用程序池上的设置。

选择应用程序池 --> 高级设置 --> 将“启用 32 位应用程序”设置为 True。

然后回收应用程序池。

【讨论】:

【参考方案15】:

在我的情况下,服务器时间不正确。所以我将服务器日期时间设置更改为自动设置时间,它解决了这个问题。

【讨论】:

【参考方案16】:

就我而言,有两个问题会引发此异常。

请注意,我的环境使用单点登录(或 STS,如果您愿意)通过 ASP.NET MVC 站点对用户进行身份验证。 MVC 站点反过来通过传递它从 STS 服务器请求的承载令牌与先前的引导令牌来对我的服务端点进行服务调用。我遇到的错误是从 MVC 站点进行服务调用时。

    WCF 服务未在我的 SSO(或 STS,如果您愿意)中配置为依赖方。

    服务配置未正确配置。特别是在 system.identityModel 的 AudienceUris 节点上。它必须与服务端点 url 完全匹配。

    <system.identityModel>
        <identityConfiguration>
            <audienceUris>
                <add value="https://localhost/IdpExample.YService/YService.svc" />
            </audienceUris>
            ....
        </identityConfiguration>
    </system.identityModel>
    

【讨论】:

【参考方案17】:

确保您的SendTimeout 在打开客户端后没有过期。

【讨论】:

【参考方案18】:

由于 BasicHttpBinding 未向我正在调用的服务发送兼容的 messageVersion,我收到此错误。我的解决方案是使用如下自定义绑定

 <bindings>
  <customBinding>
    <binding name="Soap11UserNameOverTransport" openTimeout="00:01:00" receiveTimeout="00:1:00" >
      <security authenticationMode="UserNameOverTransport">
      </security>          
      <textMessageEncoding messageVersion="Soap11WSAddressing10" writeEncoding="utf-8" />
      <httpsTransport></httpsTransport>
    </binding>
  </customBinding>      
</bindings>

【讨论】:

【参考方案19】:

试试这个:

catch (System.Reflection.TargetInvocationException e1)  
      String excType   
      excType = e1.InnerException.GetType().ToString()  
      choose case excType  
                case "System.ServiceModel.FaultException"  
                          System.ServiceModel.FaultException e2  
                          e2 = e1.InnerException  
                          System.ServiceModel.Channels.MessageFault fault  
                          fault = e2.CreateMessageFault()  
                          ls_message = "Class: uo_bcfeWS, Method: registraUnilateral ~r~n" + "Exception(1): " + fault.Reason.ToString()   
                          if (fault.HasDetail) then  
                                    System.Xml.XmlReader reader  
                                    reader = fault.GetReaderAtDetailContents()  
                                    ls_message += " " + reader.Value  
                                    do while reader.Read()  
                                              ls_message += reader.Value  
                                    loop  
                          end if  
                case "System.Text.DecoderFallbackException"  
                          System.Text.DecoderFallbackException e3  
                          e3 = e1.InnerException  
                          ls_message = "Class: uo_bcfeWS, Method: registraUnilateral ~r~n" + "Exception(1): " + e3.Message   
                case else  
                          ls_message = "Class: uo_bcfeWS, Method: registraUnilateral ~r~n" + "Exception(1): " + e1.Message  
      end choose  
      MessageBox ( "Error", ls_message )  
      //logError(ls_message)  
      return false  

【讨论】:

【参考方案20】:

<wsHttpBinding>
        <binding name="ISG_Binding_Configuration" bypassProxyOnLocal="true" useDefaultWebProxy="false" hostNameComparisonMode="WeakWildcard" sendTimeout="00:30:00" receiveTimeout="00:30:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647">
          <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
          <security mode="None">
            <message establishSecurityContext="false" clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>

【讨论】:

【参考方案21】:

我必须将 SecurityMode 更改为 Message (WSHttpBinding),然后才能正常工作。即

_wcf = new ServiceRequestClient(new WSHttpBinding(SecurityMode.Message),                     
       new EndpointAddress(_wcfRequestServerAddress));

【讨论】:

以上是关于WCF 给出不安全或不正确安全的故障错误的主要内容,如果未能解决你的问题,请参考以下文章

Azure 应用服务 - 从另一方收到不安全或不正确安全的故障。查看内部的 FaultException - Wcf

WCF 错误 - 安全处理器无法在消息中找到安全标头

现实世界中的 WCF 故障合约

如何报告MSDN文档中的错误?

WCF 安全绑定问题

使用未经检查或不安全的操作,使用 -Xlint 重新编译:未检查详细信息 [重复]