今天繼續我們的WCF分布式開發必備知識系列文章的第4節:Web Service.前3節我們分別介紹了MSMQ消息隊列\.Net Remoting\Enterprise Services三個相關的技術.並且給詳細注釋的代碼實現例子.先介紹一下本節的文章組織結構,首先還是介紹1.Web Service的基本概念2.優勢和缺點3.使用Web Service的場合4.安全問題5.實現代碼部分最後是總結.初學者就當入門資料,高手就當溫習,也歡迎提出意見.
那現在我們就開始今天的學習,網上關於Web Service的資料很多,但是也很雜亂,混淆了基本概念.
1.Web Service的基本概念
什麼是Web Services?Web Services 是設計支持支持機器與機器的通過網絡互操作的一種軟件系統(W3C的定義).是一組可以通過網絡調用的應用程序API.Web Services 是應用程序組件,使用開放協議進行通信,獨立的(self-contained)並可自我描述,可通過使用UDDI來發現 ,可被其他應用程序使用的功能.
Web services 平台主要涉及到XML \SOAP\WSDL\UDDI四個主要元素.我們在這裡簡要做下介紹.
(1)XML :XML是EXtensible Markup Language的縮寫,XML是一種類似於HTML的標記語言,XML是用來描述數據的,XML的標記不是在XML中預定義的,你必須定義自己的標記 XML使用文檔類型定義(DTD)或者模式(Schema)來描述數據 ,XML使用DTD或者Schema後就是自描述的語言.
(2)SOAP :SOAP(Simple Object Access Protocol)簡單對象訪問協議是在分散或分布式的環境中交換信息的簡單的協議,是一個基於XML的協議。它包括四個部分:SOAP封裝(envelop),封裝定義了一個描述消息中的內容是什麼,是誰發送的,誰應當接受並處理它以及如何處理它們的框架;SOAP編碼規則(encoding rules),用於表示應用程序需要使用的數據類型的實例; SOAP RPC表示(RPC representation),表示遠程過程調用和應答的協定;SOAP綁定(binding),使用底層協議交換信息。
(3)WSDL: Web services 描述語言,它的主要構成要素有五個.Types: 定義WSDL定義中所用到的數據類型,即XML Schema Types;Message : 對一組消息的輸入和輸出參數的定義;portType : 定義Web服務的操作;Binding :描述特定服務接口的協議、數據格式、安全性和其它屬性.Services : 制定特定服務的URL和提供的調用接口,包含一組端口元素. 這樣Web services 就實現了自我描述.
(4) UDDI :Universal Description Discovery and Integration即統一描述、發現和集成協議。UDDI同時也是Web服務集成的一個體系框架。它包含了服務描述與發現的標准規范。UDDI規范利用了W3C和Internet工程任務組織(IETF)的很多標准作為其實現基礎,比如擴展標注語言(XML),HTTP和域名服務(DNS)這些協議。有了它我們的Web services 就可以注冊到UDDI中心.供其客戶查找使用.
Web services 一般分為4類:
(1)面向業務的服務(Business-Oriented Web Service): 該類服務針對的是那些面向企業應用服務;
(2)面向客戶的服務(Consumer-Oriented Web Service): 此類服務針對的是那些原先的B2C的網站的改造,比如我們完全就可以在個人理財桌面系統中集成(調用)Internet上的股票價格查詢Web服務、機票預定Web服務等,使得個人理財應用的自動化程度更高。
(3)面向設備的服務(Device-Oriented Web Service): 此類服務的使用終端一般是手持設備和日用家電,比如Palm、PocketPC、手機等。。
(4)面向系統的服務(System-Oriented Web Service): 一些傳統意義上的系統服務,比如用戶權限認證,系統監控等,譬如跨國企業的所有在線服務可以使用同一個用戶權限認證Web服務。
2.Web Service優勢和缺點
我們先來了解以前平台的缺點.中間件平台(RMI, Jini, CORBA, DCOM 等等)提供了強大的服務實現手段,但是,這些系統有一個共同的缺陷,那就是它們無法擴展到互聯網上:它們要求服務客戶端與系統提供的服務本身之間必須進行緊密耦合,即要求一個同類基本結構。不支持跨平台的信息交換.而對比後我們就發現, Web Service 的很顯然具有以下優點:
(1)跨平台:WebService完全基於XML(可擴展標記語言)、XSD(XMLSchema)等獨立於平台、獨立於軟件供應商的標准;
(2)自描述:Web Service 使用WSDL標准語言進行自我描述,包括服務的方法\參數\類型\返回值等相關的完備信息.
(3)模塊化:Web Service 是應用程序組件,我們可以使用任何開發平台來開發,並且按照模塊進行封裝.
(4)跨放火牆:Web Service 使用http協議進行通信,可以穿越防火牆.
Web Service 的缺點也很明顯:
(1)效率低下,不適合做單應用系統的開發.
(2)安全問題,Web Service的沒有自身的安全機制,必須借助http協議或IIS等宿主程序實現信息安全加密
3.Web Service使用的場合
那麼什麼時候應該使用Web Service,從上面的總結我們可以看出.使用Web Service能夠帶來利益的情況.
(1)跨防火牆的通信
(2)應用程序集成,主要是指企業應用系統的集成.
(3)B2B的集成,主要是指電子商務平台的集成.
(4)軟件和數據重用,軟件重用是一個很大的主題,重用的形式很多,重用的程度有大有小。最基本的形式是源代碼模塊或者類一級的重用,另一種形式是二進制形式的組件重用。
有一些情況,不適合使用WebService。
(1)單機應用程序
單機應用程序如office等,可以直接調用系統WindowsAPI\COM進行編程,實現功能效率更高.
(2)局域網的同構應用程序
例如在局域網裡,使用COM+和.NET Remoting進行通信,會獲得更高的效率.我們不需要使用WebService.
4.Web Service安全問題
安全問題是開發和部署Web service涉及最多的問題,主要還是防止重要信息的洩露.包括非法請求和惡意攻擊.網絡常見的安全問題Web service都會面臨.
Web service的部署方式一般包括3種:
(1)IIS托管.這個最簡單,直接借助IIS,發布方式類網站發布.
(2)Console.可以駐留在控制台程序中.
(3)Windows Service.駐留在系統服務中.
最常見的就是Web service通過IIS托管發布,這個方式好處是它可以使用所有的ASP.Net的認證授權機制。
Web service處在表示層和業務邏輯層之間.當然它可以直接地與數據庫交互.簡單的驗證辦法就是調用方法裡實現對請求的合法性的判斷.通過驗證我們就執行Web Method,返回用戶數據簡單的辦法是使用System.Web.Services.Protocols.SoapHeader的類。來傳遞客戶票據到服務器進行驗證.下我們我們將實現簡單的Web service和驗證機制.
通過IIS部署的Web Service,安全也可以通過iis網站屬性裡設置。包括
(1)身份驗證和屬性控制,可以集成Windows驗證、域服務器驗證、.Net Passport驗證。如下圖。
(2)IP域名限制,只允許特定的ip或者域內機器訪問,對非法的請求進行過濾,如下圖。
(具體實現可以baidu)
5.Web Service開發
Web Service開發十分簡單,利用Visual Studio 2005\8都有清楚的向導,在新建web項目裡,選擇Web Service服務即可.如圖.
我們今天的開發流程主要包括一下4步:
1).創建一個類繼承自SOAPheader,來接收 SOAP header裡的消息。
2).添加一個方法在服務端Web service類和客戶端(添加引用會自動生成服務端類的代理)。
3).添加屬性SoapHeaderAttribute到 Web service類和客戶端代理服務類的方法上。
4).可以在客戶端訪問代理類設置SOAPheader的票據值,服務端判斷客戶端SOAPheader裡的票據值。根據驗證結果是否相應調用。
首先定義一下自己的MySOAPheader類,繼承自SOAPheader.和web service一個項目.主要是傳遞用戶的票據,自己可以實現更復雜的定義,包括用戶名稱和密碼等,這裡只做了簡單的實現,為了demo.代碼如下:
1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Web;
5 using System.Web.Security;
6 using System.Web.UI;
7 using System.Web.UI.WebControls;
8 using System.Web.UI.WebControls.WebParts;
9 using System.Web.UI.HtmlControls;
10 using System.Web.Services;
11 using System.Web.Services.Protocols;//SoapHeader處於此命名空間
12/**//// <summary>
13/// Coded By Frank Xu Lei 2/17/2009 http://www.cnblogs.com/frank_xl/
14/// MySoapHeader 定義用來傳遞來自用戶的 Soap消息的Soap Header信息
15/// </summary>
16public class MySoapHeader : SoapHeader//用戶自定義SoapHeader類必須繼承於SoapHeader
17{
18 //屬性,存儲用戶票據
19 private string _token;
20 //構造函數
21 public MySoapHeader()
22 {
23 //
24 // TODO: Add constructor logic here
25 //
26 }
27 //重載構造函數
28 public MySoapHeader(string sToken)
29 {
30 this._token = sToken;
31
32 }
33 //屬性訪問器
34 public string Token
35 {
36 get { return this._token; }
37
38 set { this._token = value; }
39 }
40}
41
用戶自定義SoapHeader類必須繼承於SoapHeader.
其次.另外一個實現用戶信息驗證的類,獨立出來,主要是為了說明驗證的框架,用戶可以在此實現訪問數據庫驗證等更復雜的實現.具體代碼如下
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4namespace WebServiceUserValidation
5{
6 public class UserValidation
7 {
8 public UserValidation()
9 {
10 }
11 //定義一個方法,判斷用戶名和密碼是否有效
12 public static bool IsUserLegal(string sName,string sPsw)
13 {
14 //用戶可以訪問數據庫進行用戶和密碼的驗證
15 //這裡為了說明用戶密碼的校驗,僅僅作了簡單的比較,不作實現
16 string psw ="FrankXuLei";
17 if (string.Equals(psw, sPsw))
18 {
19 return true;
20 }
21 else
22 {
23 return false;
24 }
25 }
26 //定義一個方法,判斷用戶票據是否有效
27 public static bool IsUserLegal(string sToken)
28 {
29 //用戶可以訪問數據庫進行用戶票據驗證
30 //這裡為了說明用戶票據的校驗,僅僅作了簡單的比較,不作實現
31 string psw = "FrankXuLei";
32 if (string.Equals(psw, sToken))
33 {
34 return true;
35 }
36 else
37 {
38 return false;
39 }
40 }
41 }
42}
43
用戶可以訪問數據庫進行用戶和密碼的驗證,這裡為了說明用戶密碼的校驗,僅僅作了簡單的比較,不作實現.
再次定義Web Service服務類.代碼如下,添加剛才實現的UserValidation類庫.要在服務裡使用.代碼如下:
1 using System;
2 using System.Web;
3 using System.Web.Services;
4 using System.Web.Services.Protocols;
5 using WebServiceUserValidation;
6//定義WebService的命名空間,為避免重復,通常設置為URL地址
7[WebService(Namespace = "http://www.cnblogs.com/frank_xl/")]
8//Coded By Frank Xu Lei,2/17/2009
9[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
10public class FrankXuWebService : System.Web.Services.WebService
11{
12 //存儲包含用戶票據Soap Header信息的屬性字段,MySoapHeader繼承自SoapHeader,我們在服務端定義實現
13 public MySoapHeader _authenticationToken;
14 private const string _token = "FrankXuLei";//長屬性字段,存儲我們服務器端的票據,
15 //
16 public FrankXuWebService()
17 {
18
19 //Uncomment the following line if using designed components
20 //InitializeComponent();
21 }
22 //定義SoapHeader傳遞的方向,
23 //SoapHeaderDirection.In;只發送SoapHeader到服務端
24 //SoapHeaderDirection.Out;只發送SoapHeader到客戶端
25 //SoapHeaderDirection.InOut;發送SoapHeader到服務端和客戶端
26 //SoapHeaderDirection.Fault;服務端方法異常的話,會發送異常信息到客戶端
27 [SoapHeader("_authenticationToken")]
28 //設置方法SoapHeader屬性,用於WebService的方法處理Soap Header消息
29 //"_authenticationToken"就是定義的FrankXuWebService類的私有屬性名稱,
30 [WebMethod(EnableSession=false)]
31 public string HelloFrank()
32 {
33
34 //要想在浏覽器直接使用Invoke測試服務,這個用戶票據代碼要注銷,不然會無法調用
35 if (_authenticationToken != null && UserValidation.IsUserLegal(_authenticationToken.Token ))//驗證票據的值是否正確,
36 {
37 return "Hello Frank,WebMethod is called sucessfully";
38 }
39 else
40 {
41 throw new Exception("Authentication Failed");
42 }
43 }
44
45}
46
定義SoapHeader傳遞的方向,SoapHeaderDirection.In;只發送SoapHeader到服務端,SoapHeaderDirection.Out;只發送SoapHeader到客戶端,SoapHeaderDirection.InOut;發送SoapHeader到服務端和客戶端SoapHeaderDirection.Fault;服務端方法異常的話,會發送異常信息到客戶端.
最後建立控制台客戶端,添加本地項目的web service引用,會生成一個代理類.這個負責和服務器段的交互.具體代碼:
1
2namespace ConsoleWebServiceClient
3{
4 class Program
5 {
6 static void Main(string[] args)
7 {
8
9 //實例化一個簡單對象訪問協議的頭,SoapHeader
10 localhost.MySoapHeader mySoapHeader = new ConsoleWebServiceClient.localhost.MySoapHeader();
11 //對象設置客戶端知道的票據的值
12 mySoapHeader.Token = "FrankXuLei";
13 string sResult = string.Empty;
14 localhost.FrankXuWebService frankXuWebService = null;
15 try
16 {
17 //實例化一個客戶端引用Web服務的類
18 frankXuWebService = new ConsoleWebServiceClient.localhost.FrankXuWebService();
19 //設置Web服務的SoapHeader
20 frankXuWebService.MySoapHeaderValue = mySoapHeader;
21 //調用Web服務的HelloWorld()方法。
22 sResult = frankXuWebService.HelloFrank();
23 //輸出結果
24 Console.WriteLine(sResult);
25 }
26 catch (Exception ex)
27 {
28 //
29 Console.WriteLine("Call WebService is failed");
30 throw ex;
31 }
32 finally
33 {
34 //釋放托管資源
35 if (frankXuWebService != null)
36 frankXuWebService.Dispose();
37 }
38
39 //調試
40 Console.WriteLine("Press any key to continue");
41 Console.ReadLine();
42
43 }
44 }
45}
46
實例化一個客戶端引用Web服務的代理類, frankXuWebService = new ConsoleWebServiceClient.localhost.FrankXuWebService();設置Web服務的SoapHeader frankXuWebService.MySoapHeaderValue = mySoapHeader;調用Web服務的HelloWorld()方法。sResult = frankXuWebService.HelloFrank();輸出結果:如下圖:
上圖顯示了調用結果的成功,當客戶端傳遞的票據正確的時候,服務方法會正確執行.返回客戶端結果.否則執行將失敗.
6.總結.
本文基本上介紹了Web Service的基本概念\優勢和缺點\使用Web Service的場合\安全問題\實現代碼部分,如何創建一個web服務和使用簡單的認證機制SoapHeader來獲取和驗證用戶請求的合法性.這個只是解決服務器端驗證的問題.但是沒有實現數據傳遞的加密.用戶的密碼信息的洩露也是Web Service的安全隱患.另外使用SSL(是Secure Sockets Layer通訊協議)用來保護傳輸中的資料,把在網頁以及服務器之間的數據傳輸加密起來,在利用iis的安全認證機制,結合幾重措施,才能很好地保護Web Service的安全.WSE也可以實現Web Service的通信安全.由於其涉及知識交多,篇幅限制不在這裡多詳細敘述.網上的資料不多,大部分是英文,我打算專門補充一個WSE安全開發系列文章,與大家進行學習.有興趣的朋友可以繼續關注.
另外本文也是這個系列的最後一節,基本上對之前的分布式開發的幾個技術都做了回顧.這個也是對我們學習WCF分布式開發打了一個很好的基礎.開發的很多知識都有相似之處.我們博學才能融會貫通.才能更好地學習WCF.希望此系列文章對大家有所幫助.謝謝!~~
本文配套源碼