在項目開發,我們經常會使用WebService,但在使用WebService時我們經常會考慮到了WebService是安全問題,很容易想到通過一組用戶名與密碼來防止非法用戶的調用 。
一、NetworkCredential方式
在 System.Net 命名空間中提供了一個NetworkCredential,通過它我們可以在網絡中提供一個憑證,只有獲得該憑證的用戶才能訪問相應的服務的權限。在NetworkCredential 中,我們通過提供WebService發布所在的服務器名稱,以及登錄服務器並調用該WebService的用戶名及密碼(在IIS中配置)。
在調用WebService時設置其Credential屬性,把上面得到的Credential憑證賦值給它,這樣只有使用提供的用戶名及密碼才能調用WebService服務了而其他用戶則無法訪問,這樣就能能滿足防止WebService被別人調用了。
至於主機名,用戶名及密碼,對於B/S可以通過webconfig來配置;對於C/S可以使用應用程序配置文件。如下以C/S為例來說明,首先我們提供一個服務器網絡憑證,然后通過WebRequest來驗證連接是否成功。當然了,為了保存用戶名與密碼等的安全,可以對其進行加密等手段來保證其安全。
/// <summary> /// 服務器網絡憑證 /// </summary> /// <returns></returns> public static NetworkCredential MyCred() { string loginUser = Properties.Settings.Default.UserName;//用戶名 string loginPSW = Properties.Settings.Default.UserPSW;//密碼 string loginHost = Properties.Settings.Default.HostName;//主機名,可以是IP地址,也可以服務器名稱 NetworkCredential myCred = new NetworkCredential(loginUser, loginPSW, loginHost); //NetworkCredential myCred = new NetworkCredential("username", "123456", "yourip");//"username", "123456", "yourservername" return myCred; }
/// <summary> /// 驗證是否成功連接到服務器,若連接成功,則返回TRUE /// </summary> /// <param name="url">服務器WebService URL</param> /// <returns></returns> public static bool Credential(string url) { //定義局部變量 string url = G_Url; //服務器驗證只驗證到機器 try { if (myWebResponse == null) { WebRequest myWebRequest = WebRequest.Create(url);//根據URL創建一個連接請求 myWebRequest.Credentials = MyCred();//獲取驗證的憑證,這是最重要的一句 myWebRequest.Timeout = 20000;//單位為毫秒 myWebResponse = myWebRequest.GetResponse();//返回連接成功時的信息 } } catch (WebException wex)//無法連接到服務器,可能是因為服務器錯誤或用戶名與密碼錯誤 { if (myWebResponse != null)//毀銷 { myWebResponse.Close(); myWebResponse = null; } return false; } catch (Exception ex) { if (myWebResponse != null) { myWebResponse.Close(); myWebResponse = null; } return false; } finally { } return true; } private static WS_Webasic.WS_Webasic webasic = null;//實現華WS_Webasic.WS_Webasic /// <summary> /// WS_Webasic初始化 /// </summary> public static WS_Webasic.WS_Webasic WS_Webasic { get { if (webasic == null)//若webasic 為空,則重新實例化,這樣可以減少驗證的時間,提高效率 { //webasic = new ZEDI.WS_Webasic.WS_Webasic(); //wsBool = Credential(webasic.Url);//URL改為服務器地址 2009-02-25 陳輝聰 chhuic@163.com wsBool = Credential(G_Url); if (wsBool == true) //服務器連接驗證通過 { webasic = new WS_Webasic.WS_Webasic();//實例化 webasic.Credentials = MyCred();//得到服務器連接憑證,這樣該WebService可以放心的連接了 } } return webasic; } }
注:
(1)必須引用 System.Net;
(2)對WebService發訪問,在IIS里取消匿名訪問權限,若允許匿名訪問,就沒有必須提供驗證憑證了。
二、
在第一種方法的基礎上對WebService里的方法進行加密,這里面方法很多,下面提供一種比較常用的方法。在調用方法時多提供兩個參數用戶加密解密用(當然了提供幾個參數看自己的需要而定)。比如有個WebService方法是根據顧客ID獲取數據庫中的顧客的詳細資料為GetCustomerDetailByCustomerID(string custID);如果只提供一個參數,則很容易被別人訪問調用,從而顧客資料很容易被別人獲取,因此我們對這個方法進行加密GetCustomerDetailByCustomerID(string scustID,string custID,ecustID);這樣,只有提供正確的scustID與ecustID這二個參數才能成功調用這個方法,而對於這二個參數scustID與ecustID,則可以通過加密方法生成一個字符串,如scustID='C39134558',ecustID='C39223525',只有這二個參數滿足一定的條件時才算驗證通過,而對於參數來說,我們也可以提供一個驗證,如果scustID里的值C39134558,前面三位必須是C39,緊跟5位13455則相加后的值18進行位操作如,對值18加一個因子,如1,則出現以下的運行:(18+1)%11==8,這樣只有最后一位為8才算這個參數值是符合要求的,所以隨便輸入一個參數如:C39134556,則因為不符合要求,所以驗證不能通過。在這里即使二個參數scustID='C39134558',ecustID='C39223525'都對了,則還需要通過這二個參數的進一步的驗證才能算成功。至於這二個滿足什么要求,一種是可以采用現有的加密機制,也可以自己寫一個加密類來襪。 上面只是舉一個簡單的例子。
通過上面的二個步驟,則可以實現比較安全的WebService調用了。
三、通過通過SOAP Header身份驗證
1、我們實現一個用於身份驗證的類,文件名MySoapHeader.cs
MySoapHeader類繼承自System.Web.Services.Protocols.SoapHeader。且定義了兩個成員變量,UserName和PassWord,還定義了一個用戶認證的函數ValideUser。它提供了對UserName和PassWord檢查的功能。
using System.Web.Services; using System.Web.Services.Protocols; /// <summary> ///MySoapHeader 的摘要說明 /// </summary> public class MySoapHeader:SoapHeader { public MySoapHeader() { // //TODO: 在此處添加構造函數邏輯 // } public string UserName; public string PassWord; public bool ValideUser(string in_UserName, string in_PassWord) { if ((in_UserName == "zxq") && (in_PassWord == "123456")) { return true; } else { return false; } } }
2.下面我們創建WebService.asmx,WebService.cs代碼如下:
using System; using System.Collections; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; /// <summary> ///WebService 的摘要說明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WebService : WebService { public WebService() { //如果使用設計的組件,請取消注釋以下行 //InitializeComponent(); } public MySoapHeader header; ////定義用戶身份驗證類變量header [WebMethod(Description = "用戶驗證測試")] [SoapHeader("header")]//用戶身份驗證的soap頭 public string HelloWorld(string contents) { //驗證是否有權訪問 if (header.ValideUser(header.UserName, header.PassWord)) { return contents + "執行了"; } else { return "您沒有權限訪問"; } } }
3.客戶端,創建個Default.aspx
using System; using System.Configuration; using System.Data; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { com.cn1yw.WebService test = new com.cn1yw.WebService();//web引用(改成您自己的) com.cn1yw.MySoapHeader Header = new com.cn1yw.MySoapHeader();//web引用創建soap頭對象(改成您自己的) //設置soap頭變量 Header.UserName = "zxq"; Header.PassWord = "123456"; test.MySoapHeaderValue = Header; //調用web 方法 Response.Write(test.HelloWorld("我是強")); } }
四、通過集成windows身份驗證
使用 NTML 或 Kerberos 對客戶端進行身份驗證。
1、將web服務程序設為集成windows身份驗證
2、客戶端web引用代碼
Test.WebReference.Service1 wr = new Test.WebReference.Service1(); //生成web service實例 wr.Credentials = new NetworkCredential("guest","123"); //guest是用戶名,該用戶需要有一定的權限 lblTest.Text = wr.Add(2,2).ToString(); //調用web service方法
該方案的優點是比較安全,性能較好,缺點是不便於移植,部署工作量大。
