2015-05-20 64 views
2

我已經開發了一個WCF雙工服務和Windows Winforms客戶端通過net.tcp雙工綁定進行通信的連接器。在IIS 7中使用net.tcp綁定承載WCF服務(從外部無法訪問)

兩者都在我的LAN上進行通信並正常工作,WCF服務在Windows 8工作站上的IIS 7上託管。

然後,我嘗試在運行Windows Server 2008 R2的租用專用服務器上使用固定IP地址((94.23.220.199),運行IIS 7和.Net 4.5.2)在Web上託管WCF服務。

WCF服務已安裝在/ ScgBroadcastorService虛擬路徑上,並且net.tcp協議已被激活。 (實際上,所有的IIS配置都與我局域網上的個人IIS完全相同)。因此,應該可以從外部訪問以下URL:「http://94.23.220.199/ScgBroadcastorService/Service.svc」。

如果您從您的瀏覽器訪問此鏈接,您將通過兩個wsdl鏈接獲得正確的「ScgBroadcastorService服務」頁面。 (這些鏈接正確地指「94.23.220.199」的IP地址。

如果一個用戶點擊此鏈接一個正確獲取WSDL XML文檔。

如此以來,WSDL文檔可以從外部訪問,我期望客戶端能夠與WCF服務進行通信。

但是,如果我啓動客戶端,我會得到以下異常:(對不起,我的家用電腦本地化爲法語...根異常是「服務器拒絕客戶證書「)

以下是完整的跟蹤:

System.ServiceModel.Security.SecurityNegotiationException: Le serveur a rejeté les informations d'identification du client. ---> System.Security.Authentication.InvalidCredentialException: Le serveur a rejeté les informations d'identification du client. ---> System.ComponentModel.Win32Exception: La tentative d’ouverture de session a échoué 
    --- Fin de la trace de la pile d'exception interne --- 
    à System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.StartReceiveBlob(LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.CheckCompletionBeforeNextReceive(LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.CheckCompletionBeforeNextSend(Byte[] message, LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.StartReceiveBlob(LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.CheckCompletionBeforeNextReceive(LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult) 
    à System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult) 
    à System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, ChannelBinding binding, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) 
    à System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) 
    à System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity) 
    --- Fin de la trace de la pile d'exception interne --- 

Server stack trace: 
    à System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity) 
    à System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream stream) 
    à System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator upgradeInitiator, IConnection& connection, ClientFramingDecoder decoder, IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper& timeoutHelper) 
    à System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper) 
    à System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(IConnection connection, TimeoutHelper& timeoutHelper) 
    à System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout) 
    à System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout) 
    à System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    à System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout) 
    à System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    à System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout) 
    à System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade) 
    à System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) 
    à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) 
    à System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) 

請注意,如果我直接從主機啓動客戶端,使用相同的客戶端配置文件,客戶端連接並完美通信!

這是當前已安裝的託管服務的服務器上的web.config文件:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <appSettings> 
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 
    </appSettings> 
    <system.web> 
    <compilation debug="true" /> 
    </system.web> 
    <system.serviceModel> 
    <services> 
     <service name="ScgServiceLibrary.ScgBroadcastorService"> 
     <endpoint binding="netTcpBinding" contract="ScgServiceLibrary.IScgBroadcastorService"> 
      <identity> 
      <servicePrincipalName value="host/94.23.220.199" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> 
      <serviceDebug includeExceptionDetailInFaults="False" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 
</configuration> 

,這裏是我一直在外面和從主機使用客戶端配置文件:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
    </startup> 
    <system.serviceModel> 
     <bindings> 
      <netTcpBinding> 
       <binding name="NetTcpBinding_IScgBroadcastorService"> 
       <security mode="None"></security> 
       </binding> 
      </netTcpBinding> 
     </bindings> 
     <client> 
      <endpoint address="net.tcp://94.23.220.199/ScgBroadcastorService/Service.svc" 
       binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IScgBroadcastorService" 
       contract="ScgServiceLibrary.IScgBroadcastorService" name="NetTcpBinding_IScgBroadcastorService"> 
       <identity> 
        <servicePrincipalName value="host/94.23.220.199" /> 
       </identity> 
      </endpoint> 
     </client> 
    </system.serviceModel> 
</configuration> 

請注意,我已經加入了

<serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 

線在web.c結束在服務器上創建onfig文件,以便在兩個wsdl鏈接上獲得具有IP地址的服務頁面。如果沒有這一行,這兩個鏈接將包含計算機名「ns304385」而不是IP地址,當然也不能從外部獲取wsdl。

謝謝你幫莫來解決剩餘的部署問題..我現在stucked,不知道怎樣做才能讓我的客戶,達到在網絡上託管我的WCF服務...

+0

是否在IIS中的網站上激活** net.tcp **綁定(808:*)?很確定用於WPA的_Net.Tcp Listener Adapter_Windows系統也需要運行 – MickyD

+0

我已經在IIS中託管的ScgBroadcastorService應用程序的高級設置中激活了net.tcp協議。你是這個意思嗎 ? –

+0

是的,「net.tcp偵聽器適配器」服務正在運行。 –

回答

3

好吧,我終於解決了半夜的問題...

我過了關的安全性netTcpBinding在兩邊。

但它不是那麼簡單,瞭解如何關閉它在服務器端的要求雙工通信的合同。

這裏是web.config文件:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <appSettings> 
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 
    </appSettings> 
    <system.web> 
    <compilation debug="true" /> 
    </system.web> 
    <system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
     <binding name="customTcpBinding" maxReceivedMessageSize="5242880" maxConnections="10"> 
      <readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384" 
         maxBytesPerRead="4096" maxNameTableCharCount="16384"/> 
      <security mode="None"></security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <services> 
     <service name="ScgServiceLibrary.ScgBroadcastorService"> 
     <endpoint binding="netTcpBinding" bindingConfiguration="customTcpBinding" contract="ScgServiceLibrary.IScgBroadcastorService"> 
      <identity> 
      <servicePrincipalName value="host/94.23.220.199" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> 
      <serviceDebug includeExceptionDetailInFaults="False" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 
</configuration> 

訣竅是添加customTcpBinding設置安全模式爲「無」,並指與bindingConfiguration屬性的端點,這個新的綁定。

不知道閹了customTcpBinding的所有參數都是最優的,但他們確定了一個雙工合同。 (我第一次嘗試被拒絕了雙工協定)

在客戶端,我也不得不設置綁定爲「無」的安全模式。這是在客戶端上我的新的配置文件:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
    </startup> 
    <system.serviceModel> 
     <bindings> 
      <netTcpBinding> 
       <binding name="NetTcpBinding_IScgBroadcastorService"> 
        <security mode="None"></security> 
       </binding> 
      </netTcpBinding> 
     </bindings> 
     <client> 
      <endpoint address="net.tcp://94.23.220.199/ScgBroadcastorService/Service.svc" 
       binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IScgBroadcastorService" 
       contract="ScgServiceLibrary.IScgBroadcastorService" name="NetTcpBinding_IScgBroadcastorService"> 
       <identity> 
        <servicePrincipalName value="host/94.23.220.199" /> 
       </identity> 
      </endpoint> 
     </client> 
    </system.serviceModel> 
</configuration> 

最後我的WCF的Windows客戶端的WinForm正常工作和我的雙面WCF服務溝通!

我不得不說,解決這個問題是一個真正的噩夢......

希望我的問題,這個完整的描述將幫助其他developpers試圖舉辦的雙工的net.tcp綁定的WCF服務在網絡上和無聊在找到修改其配置文件的正確方法之前發生所有意外的異常。

晚安人!只有三個小時,返回工作之前睡覺... :-(

+0

'安全模式=「無」 - - 通過互聯網發送憑證沒有風險嗎? – MickyD

+0

據我所知,在客戶端和服務器端都將安全模式設置爲「無」意味着根本沒有發送和檢查任何憑證。 –

+0

我不這麼認爲。 http://stackoverflow.com/questions/2748115/wcf-disabling-security-in-nettcpbinding-c和https://msdn.microsoft.com/en-us/library/ms734784(v=vs.110).aspx 。如果您在有效負載中放入證書,它將以未加密方式傳輸。 – MickyD

-1

哇 !我剛剛找到了部分解決方案!

至少解釋爲什麼我無法從外部到達WCF服務!

閱讀本:https://social.msdn.microsoft.com/Forums/vstudio/en-US/1551b4e1-8e15-4da2-b155-d398379809b3/the-server-has-rejected-the-client-credentials-in-wcf?forum=wcf

於是,我就比我用我家的電腦上的帳戶相同的名稱和密碼在服務器上創建一個帳戶,當我嘗試啓動客戶端和... ... 有用 !!!

當然,你和我同意這一點是不行的......

我希望我的WCF服務beeing能夠從用戶從網上的任何地方,用自己的用戶名/密碼登錄我接受客戶CONNEXIONS不想在意!

因此,繼續搜索上的另一種方式......如何讓WCF客戶端連接,而無需創建我的服務器上的帳戶?

敬請期待...希望很快就會找到答案......

0

設置安全模式設置爲「無」是不是你要解決這個問題,因爲設置安全無還將刪除機密性(加密)和完整性的方式(簽約)的消息。

<security mode="None"></security> 

要刪除的身份驗證,您可以: 1)設置安全模式的消息

<bindings> 
    <netTcpBinding> 
     <binding name="NetTcpBinding_IScgBroadcastorService"> 
      <security mode="Message"> 
       <message clientCredentialType="None" /> 
      </security> 
     </binding> 
    </netTcpBinding> 
</bindings> 

2)或設置安全模式,以運輸

<bindings> 
    <netTcpBinding> 
     <binding name="NetTcpBinding_IScgBroadcastorService"> 
      <security mode="Transport"> 
       <transport clientCredentialType="None" /> 
      </security> 
     </binding> 
    </netTcpBinding> 
</bindings> 

我不得不承認我沒有用你的代碼試試這個。 只是想確保閱讀這些內容的人知道認證和消息安全不是一回事,並且指向正確的方向。

相關問題