RemotingIIS承載方式

javaprogramers發表於2006-05-14
這裡來說一下iis承載方式,順便簡單說一下remoting的通道和【複雜物件】中的遺留問題。

首先明確一點:iis來承載的話只能是http通道方式的。

我們來建立一個web專案,比如叫remoting,刪除專案中的所有webform,把遠端物件dll-RemoteObject.dll複製到專案的dll資料夾下面,然後開啟web.config進行服務端設定:
<configuration>
    
<appSettings>
            
<add key="strconn" value="server=(local);uid=sa;pwd=;database=UBISOFT" />
    
</appSettings>
    
<system.runtime.remoting>
        
<application>
            
<service>
                
<wellknown type="RemoteObject.MyObject,RemoteObject" objectUri="MyObject.soap"
                    mode
="SingleCall" />
            
</service>    
            
<channels>
                
<channel ref="http"/>
            
</channels>    
        
</application>
    
</system.runtime.remoting>
</configuration>

來分析一下這個config:
1、可能大家還不是很理解type屬性,其實type屬性分兩部分<名稱空間.類名>,<程式集>
2、objectURi是用來表示物件的uri的,到時候我們用這個uri來連線到服務端
3、我們需要為uri指定soap(soap格式化)或者rem(二進位制格式化)字尾

要進行測試其實很簡單,我們在瀏覽器輸入:http://localhost/remoting/MyObject.soap?wsdl
進行測試,如果發生問題基本就是配置檔案的問題或者物件dll沒有正確複製到dll目錄

接下來修改一下客戶端的配置檔案就可以了,主要是修改地址。

<configuration>
 
<appSettings>
 
<add key="ServiceURL" value="http://localhost/remoting/MyObject.soap"/>
 
</appSettings>
</configuration>

iis承載方式預設是80埠,我們不需要在埠上做任何設定。還需要注意到的是iis方式,我們使用這樣的格式作為地址:
http://ip地址/虛擬目錄/遠端物件.soap

執行了客戶端以後如果我們的資料量比較大的話,就算是本機我們也能感受到延遲,比tcp方式延遲厲害很多很多,其實http方式的remoting效率比webservice還要差,具體選擇http方式的remoting還是webservice還是要看我們是不是對物件的狀態有需求。

iis的部署也是自動啟動服務的,還有一個優點就是可以結合iis的windows身份認證,這個參照一些iis的配置文章,這裡就不說了。

下面還是要來看一下兩種【通道】
    預設情況下,HTTP 通道使用 SOAP 格式化程式,因此,如果客戶端需要通過 Internet 訪問物件,則可以使用 HTTP 通道。由於這種方法使用 HTTP,所以允許客戶端通過防火牆遠端訪問 .NET 物件。將這些物件整合在 IIS 中,即可將其配置為 Web 服務物件。隨後,客戶端就可以讀取這些物件的 WSDL 檔案,以便使用 SOAP 與 Remoting 物件通訊。
    預設情況下,TCP 通道使用二進位制格式化程式。此格式化程式以二進位制格式進行資料的序列化,並使用原始套接字在網路中傳送資料。如果物件部署在受防火牆保護的封閉環境中,則此方法是理想的選擇。該方法使用套接字在物件之間傳遞二進位制資料,因此效能更好。由於它使用 TCP 通道來提供物件,因此具有在封閉環境中開銷較小的優點。由於防火牆和配置問題,此方法不能在 Internet 上使用。

因此我們也需要更根據自己的需求來選擇通道!看看remoting有這麼多可以選擇的方式:選擇啟用模式,選擇通道,選擇承載方式,如此多的選擇給了我們靈活的同時也增加了理解remoting的難度。

msdn相關章節:http://msdn.microsoft.com/library/CHS/cpguide/html/cpconChannels.asp

最後說一下前面的遺留問題,為什麼會發生這個安全異常?
http://www.cnblogs.com/lovecherry/archive/2005/05/20/159335.html

msdn說:
依賴於執行時型別驗證的遠端處理系統必須反序列化一個遠端流,然後才能開始使用它,未經授權的客戶端可能會試圖利用反序列化這一時機。為了免受這種攻擊,.NET 遠端處理提供了兩個自動反序列化級別:Low 和 Full。Low(預設值)防止反序列化攻擊的方式是,在反序列化時,只處理與最基本的遠端處理功能關聯的型別,如自動反序列化遠端處理基礎結構型別、有限的系統實現型別集和基本的自定義型別集。Full 反序列化級別支援遠端處理在所有情況下支援的所有自動反序列化類型。

我們首先來修改服務端的配置檔案:

<configuration>
    
<system.runtime.remoting>
        
<application name="RemoteServer">
            
<service>
                
<wellknown type="RemoteObject.MyObject,RemoteObject" objectUri="RemoteObject.MyObject"
                    mode
="Singleton" />
            
</service>
            
<channels>
                
<channel ref="tcp" port="9999"/>
                
<serverProviders> 
                    
<provider ref="wsdl" />
                    
<formatter ref="soap" typeFilterLevel="Full" />
                    
<formatter ref="binary" typeFilterLevel="Full" />
                    
</serverProviders>
            
</channels>
        
</application>
    
</system.runtime.remoting>
</configuration>

當然也可以用程式進行設定:
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Serialization.Formatters;

RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject.MyObject), "RemoteObject.MyObject", WellKnownObjectMode.Singleton);
            BinaryServerFormatterSinkProvider serverProvider 
= new BinaryServerFormatterSinkProvider(); 
            BinaryClientFormatterSinkProvider clientProvider 
= new BinaryClientFormatterSinkProvider(); 
            serverProvider.TypeFilterLevel 
= TypeFilterLevel.Full; 
            IDictionary props 
= new Hashtable(); 
            props[
"port"= 9999
            TcpChannel channel 
= new TcpChannel(props,clientProvider,serverProvider); 
            ChannelServices.RegisterChannel(channel); 
            Console.ReadLine();

客戶端還要用程式進行調整:
若要使用配置檔案設定反序列化級別,必須顯式指定 <formatter> 元素的 typeFilterLevel 屬性。雖然這通常是在伺服器端指定的,但您還必須為註冊來偵聽回撥的客戶端上的任何通道指定這一屬性,以控制其反序列化級別

在程式前面加上和服務端基本相同的程式碼:
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); 
            BinaryClientFormatterSinkProvider clientProvider 
= new BinaryClientFormatterSinkProvider(); 
            serverProvider.TypeFilterLevel 
= TypeFilterLevel.Full; 
            IDictionary props 
= new Hashtable(); 
            props[
"port"= 0
            TcpChannel channel 
= new TcpChannel(props,clientProvider,serverProvider); 
            ChannelServices.RegisterChannel(channel); 

這樣就可以了,注意:如果在同一個機器上面測試埠號應設為不同於伺服器端設定的埠號,推薦設定為0(遠端處理系統自動選擇可用埠)

.NET Remoting 自身不提供安全模型。然而,通過將遠端物件駐留在 ASP.NET 中並使用 HTTP 通道進行通訊,遠端物件可以使用 IIS 和 ASP.NET 提供的基本安全服務。比較而言,TCP 通道和自定義的主機可執行檔案能夠提供更高的效能,但這種組合不提供內建的安全功能。

• 若要對客戶端進行身份驗證,請使用 HTTP 通道,在 ASP.NET 中駐留物件,以及在 IIS 中禁用匿名訪問。
 
• 如果您不擔心客戶端身份驗證問題,請使用 TCP 通道,它可以提供更高的效能。
 
• 如果您使用 TCP 通道,請使用 IPSec 保護客戶端和伺服器之間的通訊通道。使用 SSL 來保護 HTTP 通道。
 
• 如果您需要對遠端資源進行受信任的呼叫,請將元件駐留在 Windows 服務中,而不是駐留在控制檯應用程式中。
 
• 始終不要向 Internet 公開遠端物件。在這種情況下,請使用 Web 服務。
應該僅在 Intranet 中使用 .NET Remoting。應該使用內部方式從 Web 應用程式訪問物件。即使物件駐留在 ASP.NET 中,也不要向 Internet 客戶端公開它們,因為客戶端必須是 .NET 客戶端。

最後,讓我們來看一篇msdn有關remoting安全的文章:
http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/BuildSucApp/BSAAsecmod11.mspx
說到這裡大家可能對remoting的一些基本知識稍微優點概念了,後續文章會繼續不斷強化這些概念!

相關文章