2012-03-13 58 views
14

我正在編寫WCF服務需要模擬和會話。
netTCP綁定肥皂安全協商失敗

這是確定當我試圖把它叫做我的本地機器上,但在遠程機器上總是有這樣的錯誤失敗:

Security Support Provider Interface (SSPI) authentication failed. The server may not be running in an account with identity 'host/hostname'. If the server is running in a service account (Network Service for example), specify the account's ServicePrincipalName as the identity in the EndpointAddress for the server. If the server is running in a user account, specify the account's UserPrincipalName as the identity in the EndpointAddress for the server.

如果我提供了一個UPN,它拋出一個身份未能例外。

這裏是我的配置:

服務器配置(APP):

<system.serviceModel>  
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="default"> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceAuthorization impersonateCallerForAllOperations="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <netTcpBinding> 
     <binding name="DataService.netTcpBinding"> 
      <readerQuotas maxArrayLength="65535" maxBytesPerRead="2147483647" maxStringContentLength="2147483647"/> 
      <reliableSession enabled="true" inactivityTimeout="24:00:00" ordered="true"/>   
      <security mode="TransportWithMessageCredential"> 
      <message clientCredentialType="Windows" /> 
      <transport clientCredentialType="Windows"/>   
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/> 
    <services> 
     <service behaviorConfiguration="default" name="DataService.DataService"> 
     <endpoint address="" binding="netTcpBinding" bindingConfiguration="DataService.netTcpBinding" 
      name="DataService.DataService" contract="DataService.IDataService"/> 
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://address:4504/"/> 
      <add baseAddress="net.tcp://address:4503/"/> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
</system.serviceModel> 

客戶端配置:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel>  
     <bindings> 
      <netTcpBinding> 
       <binding name="DataService.DataService" closeTimeout="00:01:00" 
        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" 
        transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" 
        hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
        maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" 
        maxReceivedMessageSize="65536"> 
        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
         maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
        <reliableSession ordered="true" inactivityTimeout="24.00:00:00" 
         enabled="true" /> 
        <security mode="TransportWithMessageCredential"> 
         <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
         <message clientCredentialType="Windows" algorithmSuite="Default" /> 
        </security> 
       </binding> 
      </netTcpBinding> 
     </bindings> 
     <client> 
      <endpoint address="net.tcp://address:4503/" binding="netTcpBinding" 
       bindingConfiguration="DataService.DataService" 
       contract="ataService.IDataService" name="DataService.DataService"> 
       <identity> 
       <dns value="DOMAIN"/>             
       </identity> 
      </endpoint> 
     </client> 
    </system.serviceModel> 
</configuration> 

任何幫助將不勝感激。

回答

19

Windows服務使用用戶主體名稱或服務主體名稱(documentation)註冊自己。引用該鏈接:「如果服務在LocalSystem,LocalService或NetworkService帳戶下運行,則默認情況下以主機/的形式生成服務主體名稱(SPN),因爲這些帳戶可以訪問計算機的SPN數據。如果服務使用不同的帳戶運行,Windows Communication Foundation(WCF)會以@。的形式生成UPN。「實際上,此引用與您的錯誤消息說明的內容非常相似。所以它似乎...

a)如果服務運行在本地服務帳戶或類似的標準帳戶下,那麼您需要調整您的客戶端配置文件有此,其中實際服務器的名稱是「地址」和端點在端口4503上運行:

<identity> 
    <servicePrincipalName value="host/address:4503" /> 
</identity> 

b)交替,如果你是在一個專門的服務帳戶下運行(我們稱之爲‘’關於域‘MYDOMAIN’ServiceAccount),那麼你要

<identity> 
    <userPrincipalName value="[email protected]" /> 
</identity> 

請注意,您可能需要在兩種情況下都使用完全限定的域名,包括森林和樹木級別。對於私有LAN/WAN內的簡單域,這將意味着address.MyDomain.local和[email protected]。如果您的域位於名爲MyTree的樹中,那麼它將是[email protected];如果它位於名爲MyForest的森林中,那麼它將是[email protected](以及類似的ServicePrincipalName)。完全限定名稱需要when you are using Kerberos進行驗證。

+1

這是正確的。我還會補充說,在使用IIS託管的Web服務時,身份應該與服務所在的應用程序池標識相匹配。這在一些版本的IIS(可能是7?)中從NetworkService(您將使用'NetworkService @ MACHINE-NAME'的用戶原則)更改爲AppPoolIdentity(您將使用'host/MACHINE-NAME'的服務原則)。 – qJake 2014-07-23 15:28:27

6

還有一個骯髒的黑客,張貼herehere,並here, 分析here

您可以提供虛擬服務主體名稱(SPN)。在這種情況下,WCF將不會失敗, 但可以回退到NTLM進行身份驗證,但不驗證委託人。

因此,配置:

<identity> 
     <servicePrincipalName value="dummy" > 
    </identity> 

和編程

EndpointIdentity identity = EndpointIdentity.CreateSpnIdentity("dummy"); 

使用的ChannelFactory:

Uri uri = new Uri("net.tcp://<myServer>:<myPort>/myServiceAddress"); 
    ChannelFactory channelFactory = new ChannelFactory<IMyContract>(new NetTcpBinding()); 
    channelFactory.CreateChannel(new EndpointAddress(uri, identity) 

也會起作用。