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


74

我正在尝试使用远程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档案。我consoleApp.cs使用obj.ServiceCredentials.UserName.UserName="xxxxxx"和在文件中提供用户名和密码.Password="xxxXx"

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

这是在首次访问服务时发生还是在一段时间后发生?
Sharique 2010年

没有更多细节很难说,但是听起来像远程服务正在等待未提供的凭据或身份验证。
jnoss 2011年

Answers:


135

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

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

我会打电话给eloqua.com,找出他们的服务器时间,然后将其与您的服务器时间进行比较。


2
@ user782534,如果您使用自定义绑定,则可以在config中设置偏斜,但是据我所知,您不能使用默认绑定来做到这一点。我也没有完全禁用该检查的能力。我倾向于不反对那个。
Randolpho

2
我打电话给远程服务的响应时间比我的要晚9个小时(实际上似乎在SoapUI日志上),然后出现此错误。响应头包含我的senddate,但是在SOAP UI日志上,我注意到响应时间总是比我的请求时间长9小时。怎么会这样?即使我更改了本地日期时间。Thanx
DavutGürbüz2012年

@DavutGürbüz可能是由于服务器的时间错误。如果客户端和服务器似乎都设置为同一时间,那么我将检查一台或两台计算机上的时区设置-可能他们认为它们位于两个不同的时区中,但显示的时间相同。
Randolpho

解决了我的问题。我的客户端距离服务器1分钟(!!!)。似乎WCF认为在很大的时间间隔后收到的消息是可疑的。
斯蒂芬·钟

3
@Randolpho ... hmmm ...就我而言,我正在运行WCF服务,测试服务器和测试客户端,它们都在同一台机器上运行,因此我不确定在我的情况下这可能是服务器时间歪斜...如果您可以告诉我其他...或我可以采取其他措施解决此问题,我将不胜感激!
马修·莱顿

24

尽管您的问题已使用上述解决方案之一解决了,但对于其他解决方案来说,这是另一个选择。

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

var service = new TestService();

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

这与WSHTTP端点(SOAP 1.2)不同,后者AccessDeniedException在传递无效凭据时引发。我个人发现此处包含的消息有些误导(因此,我第一次遇到该消息当然要花几分钟的时间),但是一旦我查阅了WCF诊断跟踪日志,根本原因就很清楚了。


13

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

进一步的窥探表明,如果客户端和服务器的时钟不同步(超过大约五分钟),则其他用户会遇到此错误,因为某些安全性方案依赖于同步时钟。


感谢您的答复!请检查我的app.config文件以及如何与服务器时钟同步?我只有远程服务器的.svc链接。
user179862

只要确保您的机器设置了正确的日期和时间即可。
丹尼尔·布鲁克纳

3
就我而言,服务和客户端都在同一台机器上,但是我仍然遇到异常。并且这会在某个时间(即10分钟)后发生,并且clientCredentialType是Windows
Sharique 2010年

5

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

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

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

我发现系统将时间转换为通用时间。

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


似乎无关紧要,但实际上,这可能是问题的唯一解决方案:)详细信息!
Muzzy B.

4

如果要从客户端传递用户凭证(按照下面的代码块),则该凭证应与服务器上的用户名/密码匹配。否则,您将收到此错误。

仅供参考,就我而言,我使用的是“ basicHTTPAuthentication”和“ TransportWithMessageCredential”安全模式。WCF服务托管在IIS上的https上。

var service = new TestService();

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

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


它帮助了我!错误消息没有表明我可能发送了错误的凭据,并且我无法访问服务代码,因此我处于机智。我仔细检查了一下,果然,我发错了名字。现在,我可以成功使用服务方法了。
PlayerGurl89

6
这难道不是归结为准确 的答案被@Xcalibur(2给出年前,具有完全相同的代码段)?
耶隆2015年


3

通常,当服务器中存在一些错误时会发生此异常,最常见的错误是身份验证数据库或身份验证的配置错误。在我的情况下,有不同的时钟同步,请确保客户端和服务器都具有相同的设置

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



2

在我的情况下,我使用证书进行身份验证,将certificateValidationMode设置为“ PeerTrust”,而我忘记将客户端证书安装在Windows存储区(LocalMachine \ TrustedPeople)中,以使其被服务器接受。


欢迎使用Stack Overflow!目前尚不清楚您是在建议解决问题还是在说自己也遇到同样的问题。如果是解决方案,您能否确切说明解决方案的工作原理?
SuperBiasedMan 2015年

3
@SuperBiasedMan我认为实际上很清楚。他说:“我在使用...”,“我忘记了……”。可以理解的是,当他记得要安装时,该问题已解决,因此,他建议做同样的事情:“在Windows存储区中安装客户端证书...以使其被服务器接受。”
Diego Jancic

1
我遇到了同样的问题(但就我而言,我已经在LocalMachine \ Personal上安装了证书)。我也很清楚,但是如果您需要更详细的说明,请按照以下步骤操作:1.在Windows资源管理器上,只需右键单击证书文件,选择“安装证书”。2.选择“本地计算机”,然后单击“下一步”。3.选择“将所有证书放入以下存储区”。4.单击“浏览”。5.选择适当的位置(对我来说是“个人”),然后按OK。6.按“下一步”,“完成”
法比奥·杜克·席尔瓦(FábioDuque Silva)

2

就我而言,当我将wshttpbinding协议从更改为时httpshttp它开始起作用。


1

即使服务器和客户端在同一台计算机上,我也从过时的服务参考中遇到了这个问题。如果出现此问题,运行“更​​新服务参考”通常可以解决该问题。


1

就我而言,我在测试客户端-服务器应用程序的同一台计算机上遇到此错误。但是,此问题已通过“更新服务参考”解决。

  • 图莎·瓦拉瓦卡

1

只是为了分享……我有一个罕见的案例,让我scratch了几分钟。甚至时间偏差解决方案都非常准确,而我之前曾解决过该问题,这次却有所不同。我当时在一台新的Win8.1机器上,记得有一个时区问题,并且手动调整了时间。好吧,尽管服务器和客户端上显示的时间仅相差几秒钟,但我仍然收到错误消息。我所做的是在“日期和时间设置”中激活“夏季保存选项”(请注意,我确实处于夏季保存时间,但是手动进行了时间设置),然后转到互联网时间部分并刷新了...中的时间我的电脑保持原样,但错误消失了。

希望这对任何人都有用!



0

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

请注意,我的环境使用“单一登录”(如果需要,可以使用STS)来通过ASP.NET MVC站点对用户进行身份验证。MVC站点依次通过传递它从STS服务器请求的承载令牌和先前的Bootstrap令牌来对我的服务端点进行服务调用。我收到的错误是当我从MVC站点进行服务呼叫时。

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

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

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


0

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

0

试试这个:

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  

0

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


0

在工作之前,我不得不将SecurityMode更改为Message(WSHttpBinding)。即

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

0

就我而言,这是IIS应用程序池上的设置。

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

然后回收应用程序池。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.