如何使WCF服务服务器 - 客户端时差独立?

时间:2013-08-23 10:31:03

标签: c# .net wcf web-services time

从测试客户端访问WCF服务时,我遇到以下异常:

System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when verifying security for the message.
   --- End of inner exception stack trace ---

我在互联网上搜索了这个问题的根本原因。我发现这主要是由于客户端 - 服务器时间差异造成的。但我无法找到正确的解决方案。以下是我的服务器端配置:

 <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="RequestUserName">
            <security mode="Message">
              <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" />

            </security>
        </binding>
      </wsHttpBinding>

    </bindings>
    <services>
      <service name="WCFService.Service1" behaviorConfiguration="WCFService.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="http://subdomain.domain.com/service1.svc" binding="wsHttpBinding" contract="WCFService.IService1" bindingName="RequestUserName">


        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCFService.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
          <serviceMetadata httpGetEnabled="false" />

          <!-- 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" />

        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment>
      <baseAddressPrefixFilters>
        <add prefix="http://subdomain.domain.com/"/>
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>

和客户端配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="RequestUserName_IService1" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://subdomain.domain.com/service1.svc" binding="wsHttpBinding"
                bindingConfiguration="RequestUserName_IService1" contract="ServiceReference1.IService1"
                name="RequestUserName_IService1">
                <identity>
                    <userPrincipalName value="DOMAIN\subdomaincom_web" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

任何人都可以帮我找到解决这个问题的方法。

更新:当我跟踪异常时,内部异常显示此The security timestamp is stale because its expiration time ('2013-08-21T11:17:39.482Z') is in the past. Current time is '2013-08-21T12:31:31.897Z' and allowed clock skew is '00:05:00'.

我的服务器使用UTC格式,我的客户端是一个可从任何国家/地区下载的通用应用程序。

更新2:回答后配置:

<system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="Wrabind">
          <transactionFlow />
          <security authenticationMode="SecureConversation" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <localClientSettings maxClockSkew="00:07:00" />
            <localServiceSettings maxClockSkew="00:07:00" />
            <secureConversationBootstrap messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" />
                <localClientSettings maxClockSkew="00:30:00" />
                <localServiceSettings maxClockSkew="00:30:00" />
          </security>
          <textMessageEncoding />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
    <!-- change -->
    <services>
      <service name="WCFService.Service1" behaviorConfiguration="WCFService.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="http://subdomain.domain.com/service1.svc" binding="customBinding" contract="WCFService.IService1" bindingName="Wrabind">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->

        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCFService.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
          <serviceMetadata httpGetEnabled="false" />
          <!-- change -->
          <!--<serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFService.Authentication.DistributorValidator, WrangleCoreService"/>
            <serviceCertificate findValue="WCFService" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
          </serviceCredentials>-->
          <!-- change -->
          <!-- 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" />

        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment>
      <baseAddressPrefixFilters>
        <add prefix="http://subdomain.domain.com/"/>
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <!--<standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true"
          automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>-->

  </system.serviceModel>

2 个答案:

答案 0 :(得分:3)

此错误可能有多种原因,常见的原因与服务器没有因variosu原因而验证客户端有关(可能不在同一个域中)。确定turn on wcf trace的确切原因并查看它以红色显示的错误。您正在寻找的是在跟踪UI中隐藏的inenr异常,它位于树中间的右侧。

以下是设置时钟偏差的方法:

<security authenticationMode="...">
           <localClientSettings maxClockSkew="00:07:00" />
           <localServiceSettings maxClockSkew="00:07:00" />
           <secureConversationBootstrap>
              <localClientSettings maxClockSkew="00:30:00" />
              <localServiceSettings maxClockSkew="00:30:00" />
           </secureConversationBootstrap>
</security>

注意只能在自定义绑定上定义偏斜。由于您使用WSHttpBinding,因此需要将其转换为自定义绑定,可以通过WCF binding converter在线轻松完成。

答案 1 :(得分:0)

我遇到了同样的问题,并遵循了所有建议。但我的错是我只更改了服务器配置,而我也必须更改客户端配置。

这是我没有maxClockSkew的配置

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <connectionStrings>
    <!-- -->
  </connectionStrings>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IHotLine1" closeTimeout="00:10:00"
          openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
          maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security>
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="localhost:6767/blabla.svc" binding="wsHttpBinding"
        bindingConfiguration="WSHttpBinding_IHotLine1" contract="ServiceReference2.IHotLine"
        name="WSHttpBinding_IHotLine1">
        <identity>
          <certificate encodedValue="====encodedvalue===" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

并使用时钟偏差更新

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="WSHttpBinding_IHotLine1">
          <transactionFlow/>
          <security authenticationMode="SecureConversation"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <localClientSettings maxClockSkew="01:30:00" />
            <localServiceSettings maxClockSkew="01:30:00" />
            <secureConversationBootstrap authenticationMode="UserNameForSslNegotiated"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" >
              <localClientSettings maxClockSkew="01:30:00" />
              <localServiceSettings maxClockSkew="01:30:00" />
            </secureConversationBootstrap>
          </security>
          <textMessageEncoding/>
          <httpTransport maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
        </binding>
      </customBinding>
    </bindings>
    <client>

      <endpoint address="http://localhost:6767/blabla.svc" binding="customBinding"
        bindingConfiguration="WSHttpBinding_IHotLine1" contract="ServiceReference2.IHotLine"
        name="WSHttpBinding_IHotLine1">
        <identity>
          <certificate encodedValue="====encodedvalue===" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>