Web服務(ASMX Web Service)與WCF服務(Windows Communication Foundation Service)
之前偶爾使用WCF﹐也只是將它當做原本ASP.NET傳統的Web service(ASMX web service)使用﹐並沒有實際去了解WCF和web service的區別﹐也不曾去深入為什麼要使用WCF。最近想把web service加上使用者驗證﹐打算採用SOAP Header的方式﹐這才好好的看了一下WCF和web service的不同﹐發現光安全性上就有許多的差異性。這次的筆記主要是在WCF自訂使用者認證﹐不過同時把研究過程中得到的知識一併記錄下來。
WCF提供有多種的認證技術﹐Windows認證﹑X.509憑證﹑使用者帳號/密碼認證...等。以現行的生態都是跨平台系統﹐因此Windows認證方式並不是很適合﹐因此選用自訂使用者帳號/密碼的認證方式。
1. Web服務(ASMX Web Service)與WCF服務(Windows Communication Foundation Service)比較
微軟在ASP.NET 1.0就開始支援Web Service﹐並且微軟所提供的Web Service加上IIS在開發上與使用上非常便利﹐WCF相對起來就有比較多的眉角和門檻。現今web service仍是許多ASP.NET開發者所使用﹐那麼為什麼要有WCF?WCF是不是可以完全取代web service?有一篇討論寫的不錯﹐可以參考一下。(http://social.msdn.microsoft.com/Forums/zh-CN/wcfzhchs/thread/c06420d1-69ba-4aa6-abe5-242e3213b68f)
微軟於.Net 3.0時開始導入WCF﹐希望能讓開發人員逐步取代原有的Web服務開發﹐然而在推出.Net 4.0開始 visual studio 2010其預設的網站專案中已見不到Web服務(但並非消失)﹐因為WCF的推出﹐微軟將Web Service的發展重心移到WCF上﹐原有的ASP.NET Web Service給了另一個名稱ASMX Web Service﹐那麼原有的Web服務與WCF到底有什麼不同﹐為什麼微軟希望用WCF來取代Web服務。
Web服務 |
WCF服務 |
|
.Net 版本 |
1.1或更高版本 |
3.5或更高版本 |
功能 |
必須安裝WSE之後才比較完整支援WS-* |
完整﹐本身已實作WS-*的功能。 |
安全性控管 |
彈性﹐可單獨一個網站﹐也可直接建置於已存在的網站中。 |
彈性﹐可單獨一個網站﹐也可直接建置於已存在的網站中。 |
什麼是WS-*規格﹐WS-*是許多的Web服務相關的規範﹐由不同的標準組織或機構來維護和支持。不同的標準或互相補充﹐或重疊﹑或互相競爭。這些規範沒有公認的統一所屬機構﹐因為都是以WS-為開頭﹐統稱WS-*。這些Web服務規範通常都是難以實作的部分﹐比較重要的像是以下的規格
WS-Security |
描述了如何將簽名和加密頭加入SOAP消息﹐如何在訊息中加入token。亦即與身份驗証有關﹐及加密簽章的處理。 |
WS-ReliableMessaging |
可靠消息模型﹐確保訊息至少一次﹐至多一次﹐正好一次。 |
WS-Addressing |
實際包含兩個新概念:端點引用(endpoint reference, EPR)和SOAP結構的消息資訊(message information, MI)頭。 |
WS-Trust |
對WS-Security規範的一些擴充﹐專門處理有關安全tokens的發佈﹐整新和驗証﹐確保各方參與者的相互操作在一個可信任的安全資料交換環境中。 |
WS-Federation |
跨網域單點登錄認証 |
WS-AtomicTransaction |
一種互通的交易通訊協定﹐做為異質平台﹑跨internet的分散式交易。 |
WS-*的規範除了上述提到的之外﹐仍陸續增加當中。ASP.NET Web服務本身不支援WS-*﹐必須加裝WSE﹐才能支援。目前可以安裝的WSE最新版本為WSE 3.0 (http://www.microsoft.com/download/en/details.aspx?id=14089)﹐WSE 3.0後續並不會再增加和更新﹐也就是WSE 3.0是末代版本﹐微軟希望未來大家改用WCF開發。WCF已實作WS-*的規格﹐功能性比Web服務完整。WCF所支援的WS-*的通訊協定﹐可參考http://msdn.microsoft.com/zh-tw/library/ms730294.aspx 或 http://msdn.microsoft.com/zh-tw/library/ms730879.aspx﹐的資料。
微軟除了Web服務與WCF服務﹐另外還有WCF RIA Service與WCF資料服務的伺服器端服務。
WCF RIA Service |
.Net 3.5以上版本支援 Silverlight專用﹐可用於Silverlight網頁與Windows Phone 7.x。 |
WCF資料服務 |
.Net 3.5以上版本支援 前身為ADO.NET Data Service﹐不過與ADO.NET完全無關。 可以提供服務也可以提供資料模型﹐內建REST ful介面。 只可以使用ADO.NET實體資料模型。 |
參考資料:
WS-Security維基百科(http://zh.wikipedia.org/wiki/WS-Security)
WS-ReliableMessaging維基百科(http://zh.wikipedia.org/wiki/WS-ReliableMessaging)
WS-Addressing 維基百科(http://zh.wikipedia.org/wiki/WS-Addressing)
WS-Addressing對SOAP的隱式影嚮(http://www.ibm.com/developerworks/cn/webservices/ws-address.html)
WS-Trust和WS-SecureConversation (http://www.ibm.com/developerworks/cn/java/j-jws15/index.html)
WS-Federation維基百科(http://en.wikipedia.org/wiki/WS-Federation)
WS-AtomicTransaction (http://docs.oasis-open.org/ws-tx/wstx-wsat-1.1-spec-errata-os/wstx-wsat-1.1-spec-errata-os.html)
Web服務規範列表 維基百科(http://zh.wikipedia.org/wiki/Web%E6%9C%8D%E5%8A%A1%E8%A7%84%E8%8C%83%E5%88%97%E8%A1%A8)
2. Web服務與WCF服務建置上的差異
2.1 Web服務的建立
在vs 2003﹑vs2005﹑vs2008﹐Web 服務的建置都是單獨的專案﹐建立時就是獨立的網站。由Visual Studio開發工具的功能表選擇【檔案】à【新增】à【網站】﹐在新網站中選擇【ASP.NET Web服務】﹐決定好要建立位置(網站)﹐即可建立一個Web 服務的專案。
Visual Studio 2010在建立Web服務就有一些不一樣﹐如果依上述【檔案】》【新增】》【網站】﹐會發現找不到ASP.NET Web服務。在VS 2010(.Net 4.0) 預設是沒有Web 服務﹐基本上微軟就是希望大家改用WCF﹐但並非Web服務不見了﹐在.Net 4.0 Web 服務已不是獨立專案方式存在﹐而是依付於一個網站專案之下。
因此在vs2010使用.Net Framework 4之下要使用web服務是要先建立一個ASP.NET 網站﹐然後在方案總案中再以【加入新項目】的方式﹐即可找到Web服務的項目﹐加入後跟過去Web服務完全一樣。
如果在vs 2010中仍想像以前建立ASP.NET Web服務的專案﹐那麼在一開始建立網站專案時﹐則要選擇.Net Framework為2.0﹑3.0或3.5﹐則在專案範本中一樣有ASP.NET Web服務專案可以選。
2.2 WCF服務的建立
Vs 2008﹑vs 2010由【檔案】à【新增】à【網站】選取WCF服務即可建立一個WCF服務的專案。
不過﹐這不是唯一的建置WCF服務的方式。上述的建立方式是直接以IIS做為WCF的載具﹐這是個快速做法﹐實作上WCF不限定使用IIS做為載具﹐也可以自行撰寫載具WinForm﹑Windows服務做為WCF載具都可以。
由【檔案】à【新增】à【專案】左側選取WCF﹐中間選擇「WCF服務程式庫」。這一種方式在建置後會是一個DLL檔案﹐之後不論是WinForm﹑Windows服務或者IIS都可以當作WCF載具﹐引用WCF服務程式庫提供服務。
若是使用VS 2005的會比較麻煩一點(應該是麻煩很多點….v_v)。
- 如果作業系統是Windows XP要先安裝.Net Framework 3.0
- 安裝Visual Studio Extensions for .NET Framework 3.0﹐不過這個在微軟網站上也很難找得到了﹐目前可以到以下位置下載visual studio 2005 extensions for .net framwork (wcf&wpf)( http://download.cnet.com/1770-20_4-0.html?query=The+Visual+Studio+2005+extensions+for+NET+Framework+3+0+WCF+WPF+November+2006+CTP&searchtype=downloads)。什麼時候連結點會消失﹐不知道。
WCF是在.Net 3.0時加入﹐建議要開發WCF還是使用VS 2008以上的版本才會方便﹐現在.Net Framework都己到了4.0了﹐相對的WCF也有一些改進。
3. WCF的繫結(basicHttpBinding & wsHttpBinding)
WCF提供了許多種服務繫結(binding)方式﹐其中basicHttpBinding﹑wsHttpBinding和NetTcpBinding是最常被使用的。NetTcpBinding是微軟最徍化﹐效率最高的﹐如果兩端都是微軟的solution﹐可以考慮NetTcpBinding﹐不過這不是這次想研究的。
basicHttpBinding﹐微軟在MSDN上的描述﹐BasicHttpBinding 使用 HTTP 做為傳送 SOAP 1.1 訊息的傳輸。服務可使用這個繫結公開符合 WS-I BP 1.1 的端點,例如 ASMX 用戶端取用的端點。同樣地,用戶端可使用 BasicHttpBinding 與公開符合 WS-I BP 1.1 之端點的服務通訊,例如 ASMX Web 服務或使用 BasicHttpBinding 設定的服務。安全性預設是關閉的,但是可以透過將 <basicHttpBinding> 的 <security> 子項目的模式屬性設定為非 None 的值,來新增安全性設定。根據預設,它使用「文字」訊息編碼和 UTF-8 文字編碼。
wsHttpBinding﹐MSDN上的描述﹐類似 BasicHttpBinding,不過提供更多的 Web 服務功能。它使用 HTTP 傳輸並提供訊息安全性,如同 BasicHttpBinding﹐為非雙工服務合約定義安全、可靠且互通的繫結。此繫結會實作下列規格:WS-Reliable 訊息用於可靠性以及 WS-Security 用於訊息安全性和驗證。傳輸是 HTTP,而訊息編碼是 Text/XML 編碼。
文字硬綁綁﹐直接看一下差異性﹐寫一段程式碼﹐不加其他的設定由Fiddler觀看封包的資料。這裏我先建置了一個WCF程式庫(MyProducts.lib)﹐後續的範例都是引用這一個程式庫。WCF有個好處﹐一份程式寫好後﹐後續要使用那一種載具提供服務或者要變換繫結﹐程式可以不用動﹐只要在設定檔上做手腳就可以了。
在MyProducts.lib中提供了一個方法SaySomething﹐只是要測試參數傳入﹐與資料回傳。
public string SaySomething(string value) {
return "You say [" + value + "].";
}
使用basicHttpBinding和wsHttpBinding呼叫同一個method
basicHttpBinding Request
basicHttpBinding Response
wsHttpBinding Request
wsHttpBinding Response
由封包資料可以看出﹐basicHttpBinding在預設值之下資料的傳遞都是明碼﹐這和ASP.NET 的ASMX Web Service是相同的﹐而wsHttpBinding的資料傳遞都是密文方式﹐這是wsHttpBinding預設安全性就是Message實作了WS-Reliable 訊息用於可靠性以及 WS-Security 用於訊息安全性和驗證。
basicHttpBinding和wsHttpBinding兩者只透過設定就可達到不同的效果﹐開發者不用為了如何對資料在傳遞過程加減密傷腦筯﹐basicHttpBinding也可以透過設定就讓傳遞的資料也加密﹐它只是預設不開啟而已。但﹐WCF的設定很多樣﹐對於開發者而言是另一項頭痛的地方。
看看以下兩者的設定檔﹐差別僅在於繫結(binding)不同﹐沒有動到任何的程式碼就可以達到不同的結果。
basicHttpBinding
<system.serviceModel>
<services>
<service behaviorConfiguration="Products.Behavior" name="MyProducts.lib.ProductService">
<endpoint binding="basicHttpBinding" contract="MyProducts.lib.IProductService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Products.Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
wsHttpBinding
<system.serviceModel>
<services>
<service behaviorConfiguration="Product.Behavior" name="MyProducts.lib.ProductService">
<endpoint binding="wsHttpBinding" contract="MyProducts.lib.IProductService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Product.Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
參考資料:
WCF系統提供的繫結(http://msdn.microsoft.com/zh-tw/library/ms730879(v=vs.90).aspx)