自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

WCF安全之基于自定義聲明授權(quán)策略

開(kāi)發(fā) 開(kāi)發(fā)工具
本文將介紹WCF安全之基于自定義聲明授權(quán)策略,有時(shí)我們需要做到對(duì)不同的用戶授予不同的操作契約的訪問(wèn),這就是本文討論的重點(diǎn)。

背景

我們認(rèn)為WCF可以使用自定的義的用戶名密碼方式限制對(duì)服務(wù)的訪問(wèn)和加密,有可能存在這樣一種情況,比如一個(gè)協(xié)定中存在多個(gè)操作,即一個(gè)服務(wù)契約中包含多個(gè)操作契約,如果我們還希望在同一用戶訪問(wèn)當(dāng)前服務(wù)契約的時(shí)候,更進(jìn)一步,可以讓我們做到對(duì)不同的用戶授予不同的操作契約的訪問(wèn),直白一點(diǎn),比如有兩個(gè)用戶admin、admin2,admin可以訪問(wèn)服務(wù)契約中的兩個(gè)操作契約,但是admin2只能訪問(wèn)其中一個(gè),本示例將實(shí)現(xiàn)這種需求,在以下的示例中,服務(wù):IUserData 中包含三個(gè)操作契約,我們將對(duì)admin、admin2 這兩個(gè)用戶授予不同的操作契約的訪問(wèn)權(quán)限,在客戶使用不同的用戶調(diào)用服務(wù)后,服務(wù)器將打印當(dāng)前的請(qǐng)求服務(wù)的用戶、請(qǐng)求的資源、服務(wù)器對(duì)聲明的檢查、檢查結(jié)果等數(shù)據(jù)。

開(kāi)始

首先我們建立一個(gè)自定義的基于服務(wù)授權(quán)訪問(wèn)檢查的管理器,CustomServiceAuthorizationManager,首先看代碼:

  1. public class CustomServiceAuthorizationManager : ServiceAuthorizationManager  
  2.     {  
  3.         protected override bool CheckAccessCore(OperationContext operationContext)        
  4.         {  
  5.             string action = operationContext.RequestContext.RequestMessage.Headers.Action;  
  6.             Console.ForegroundColor = ConsoleColor.Red;  
  7.             Console.WriteLine("/--分割線--嘎嘎-------------------------------------------/");  
  8.             Console.ForegroundColor = ConsoleColor.White;  
  9.             Console.WriteLine("請(qǐng)求的資源,URI:{0}", action);  
  10.             foreach (ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)  
  11.             {                 
  12.                 if (cs.Issuer == ClaimSet.System)//如果此聲明是應(yīng)用程序頒發(fā)的。  
  13.                 {  
  14.                     foreach (Claim claim in cs.FindClaims("net.tcp://UserDataService.IUserData/", Rights.PossessProperty))  
  15.                     {  
  16.                         Console.WriteLine("服務(wù)器聲明檢查,URI:{0}", action);  
  17.                         if (claim.Resource.ToString() == action)  
  18.                         {  
  19.                             Console.WriteLine("通過(guò),URI:{0}", action);  
  20.                             return true;  
  21.                         }  
  22.                     }  
  23.                 }  
  24.             }  
  25.             Console.WriteLine("不通過(guò),URI:{0}", action);  
  26.             return false;  

1、在上面的代碼中,我們首先建立了一個(gè)繼承自 System.ServiceModel.ServiceAuthorizationManager,并重寫(xiě)了其CheckAccessCore的檢查方法,或者有朋友會(huì)問(wèn),為什么不直接使用ServiceAuthorizationManager類呢?是的,沒(méi)錯(cuò),ServiceAuthorizationManager是提供自定義授權(quán)訪問(wèn)檢查的類,但是,ServiceAuthorizationManager類本身并不對(duì)任何聲明進(jìn)行評(píng)估,換句話說(shuō),此類不執(zhí)行任何基于自定義聲明授權(quán)的檢查,在默認(rèn)情況下,所有服務(wù)都是可以訪問(wèn)的,顯示,這不符合我們本次示例的業(yè)務(wù)需求。

2、ServiceAuthorizationManager類共有三個(gè)可供重寫(xiě)的方法,分別為:

(1)bool CheckAccess(OperationContext operationContext)

(2)bool CheckAccess(OperationContext operationContext, ref Message message)

(3)bool CheckAccessCore(OperationContext operationContext) 


但是,實(shí)際上,前兩個(gè)方法都是通過(guò)調(diào)用bool CheckAccessCore(OperationContext operationContext)  來(lái)實(shí)現(xiàn)對(duì)自定義授權(quán)聲明的評(píng)估,所以,我們應(yīng)該直接重寫(xiě)CheckAccessCore而不是前兩個(gè)方法。

3、在重寫(xiě)的CheckAccessCore方法內(nèi),首先通過(guò)當(dāng)前操作的上下文對(duì)象獲得了當(dāng)前客戶端所請(qǐng)求的資源定位符Action,接著,馬上調(diào)用自定義授權(quán)聲明頒發(fā)管理器,把當(dāng)前用戶的授權(quán)策略聲明集添加到服務(wù)安全上下文,并檢查此授權(quán)策略聲明集是否為當(dāng)前應(yīng)用程序所頒發(fā),如果是當(dāng)前應(yīng)用程序所頒發(fā),則查找當(dāng)前授權(quán)策略聲明中一個(gè)名為:“net.tcp://UserDataService.IUserData/”的聲明,最后,服務(wù)器再檢查如果用戶所請(qǐng)求的資源存在于此聲明中,剛授權(quán)通過(guò),否則服務(wù)將拒絕客戶端所請(qǐng)求的資源。

自定義授權(quán)策略聲明集管理器


1、為了完成此次基于自定義授權(quán)策略聲明的服務(wù)器授權(quán)檢查, 我們需要構(gòu)造自已的授權(quán)策略聲明集管理器,代碼如下:

  1. CustomAuthorizationPolicy  
  2. public class CustomAuthorizationPolicy : IAuthorizationPolicy  
  3.     {  
  4.         string id = string.Empty;  
  5.         public CustomAuthorizationPolicy()  
  6.         {  
  7.             id = new Guid().ToString();//每個(gè)聲明集都是一個(gè)唯一的  
  8.         }  
  9.  
  10.         /// <summary> 
  11.         /// 評(píng)估用戶是否符合基于此授權(quán)策略的聲明  
  12.         /// </summary> 
  13.         /// <param name="evaluationContext"></param> 
  14.         /// <param name="state"></param> 
  15.         /// <returns></returns> 
  16.         public bool Evaluate(EvaluationContext evaluationContext, ref object state)  
  17.         {  
  18.             bool flag = false;  
  19.             bool r_state = false;  
  20.             if (state == null) {tate = r_state;} else  { r_state = Convert.ToBoolean(state);}  
  21.             if (!r_state)  
  22.             {  
  23.                 IList<Claim> claims = new List<Claim>();//實(shí)體聲明集  
  24.                 foreach (ClaimSet cs in evaluationContext.ClaimSets)  
  25.                 {  
  26.                     foreach (Claim claim in cs.FindClaims(ClaimTypes.Name, Rights.PossessProperty))  
  27.                     {                         
  28.                         Console.WriteLine("用戶:{0}", claim.Resource);  
  29.                         foreach (string str in GetOprationList(claim.Resource.ToString()))  
  30.                         {  
  31.                             claims.Add(new Claim("net.tcp://UserDataService.IUserData/", str, Rights.PossessProperty));  
  32.                             Console.WriteLine("授權(quán)的資源:{0}", str);  
  33.                         }                         
  34.                     }  
  35.                 }  
  36.                 evaluationContext.AddClaimSet(this, new DefaultClaimSet(Issuer, claims));r_state = true;flag = true;  
  37.             }  
  38.             else{flag = true;}  
  39.             return flag;  
  40.         }  
  41.  
  42.         /// <summary> 
  43.         /// 賦予用戶聲明權(quán)限  
  44.         /// </summary> 
  45.         /// <param name="username"></param> 
  46.         /// <returns></returns> 
  47.         private static IEnumerable<string> GetOprationList(string username)  
  48.         {  
  49.             IList<string> lists = new List<string>();  
  50.             if (username == "admin")  
  51.             {  
  52.                 lists.Add("net.tcp://UserService.IUserData/GetData");  
  53.                 lists.Add("net.tcp://UserService.IUserData/GetUserExtensionXElement");  
  54.             }  
  55.             else if (username == "admin2")  
  56.             {  
  57.                 lists.Add("net.tcp://UserService.IUserData/GetData");  
  58.             }  
  59.             return lists;  
  60.         }  
  61.  
  62.         #region IAuthorizationComponent 成員/屬性實(shí)現(xiàn)  
  63.         public ClaimSet Issuer  
  64.         {  
  65.             get { return ClaimSet.System; }  
  66.         }  
  67.         public string Id  
  68.         {  
  69.             get { return id; }  
  70.         }  
  71.         #endregion  
  72.     } 

2、首先,我們建立了一個(gè)類CustomAuthorizationPolicy繼承自IAuthorizationPolicy接口,IAuthorizationPolicy中定義了一組用于對(duì)用戶進(jìn)行授權(quán)的規(guī)則,規(guī)則相當(dāng)簡(jiǎn)單,除了兩個(gè)屬性和一個(gè)授權(quán)規(guī)則檢查的方法,再?zèng)]有其它。

3、在類的一開(kāi)始,我們給每個(gè)即將進(jìn)行授權(quán)的客戶定義了一個(gè)聲明集,并給了一個(gè)唯一的標(biāo)識(shí)(GUID),

4、實(shí)現(xiàn)了bool Evaluate(EvaluationContext evaluationContext, ref object state),在 Evaluate中,我們通過(guò)當(dāng)前經(jīng)過(guò)評(píng)估的授權(quán)策略的結(jié)果上下文對(duì)象獲取了一個(gè)ClaimSets對(duì)象,ClaimSets包含了一組經(jīng)過(guò)評(píng)估的獲取與授權(quán)策略關(guān)聯(lián)的聲明集,實(shí)際上,包含了客戶端調(diào)用服務(wù)前添加的用戶名,這個(gè)用戶名是經(jīng)過(guò)了上一章的自定義用戶名密碼訪問(wèn)服務(wù)的驗(yàn)證程序驗(yàn)證后的用戶名,所以,我們可基于此用戶名對(duì)其權(quán)限進(jìn)行分配,即給他一個(gè)可訪問(wèn)服務(wù)操作的聲明。

5、添加聲明,在上面的代碼中,有一個(gè)方法:IEnumerable<string> GetOprationList(string username),在第4點(diǎn)中, bool Evaluate方法傳入一個(gè)用戶名,然后,GetOprationList方法將對(duì)這個(gè)用戶進(jìn)行檢查并給其添加預(yù)先定義的聲明,當(dāng)然,這個(gè)檢查你可以在持久化介質(zhì)中做,比如數(shù)據(jù)庫(kù),你大可將你的所有服務(wù)操作都做成基于角色的訪問(wèn)的聲明,現(xiàn)在這里只是一個(gè)示例,所以沒(méi)有必要做得很靈活,當(dāng)然,我也不推薦你那樣做,除非真有必要,我覺(jué)得效率上會(huì)有很大的問(wèn)題。

6、不論這個(gè)用戶的權(quán)限如何,最后, Evaluate方法都會(huì)在將一個(gè)默認(rèn)的聲明添加到當(dāng)前當(dāng)前經(jīng)過(guò)評(píng)估的授權(quán)策略的結(jié)果上下文對(duì)象中,

這一句:evaluationContext.AddClaimSet(this, new DefaultClaimSet(Issuer, claims));

7、然后,再由前面定義的服務(wù)授權(quán)策略管理器對(duì)這個(gè)聲明和用戶所請(qǐng)求的資源進(jìn)行檢查,以決定是否對(duì)該用戶所請(qǐng)求的資源授予其訪問(wèn)權(quán)限。

配置授權(quán)策略管理器和授權(quán)聲明集管理器

1、在上面的代碼完成以后,我們還需要在服務(wù)器配置文件中進(jìn)行相應(yīng)的設(shè)置,好讓我們的代碼正常工作,配置比較簡(jiǎn)單,如下:

  1. <behaviors> 
  2.       <serviceBehaviors> 
  3.           <serviceCredentials> 
  4.             <serviceCertificate findValue="192168168151service" 
  5.                                  x509FindType="FindBySubjectName" 
  6.                                  storeLocation="LocalMachine" 
  7.                                  storeName="My"/> 
  8.             <userNameAuthentication  customUserNamePasswordValidatorType="UserDataServcie.CustomUserPassword,UserDataServcie" userNamePasswordValidationMode="Custom"/> 
  9.           </serviceCredentials> 
  10.           <serviceAuthorization serviceAuthorizationManagerType="UserDataServcie.CustomServiceAuthorizationManager,UserDataServcie"> 
  11.             <authorizationPolicies> 
  12.               <add policyType="UserDataServcie.CustomAuthorizationPolicy,UserDataServcie"/> 
  13.             </authorizationPolicies> 
  14.           </serviceAuthorization> 
  15. </behavior> 

2、其中紅色部分是對(duì) 授權(quán)策略管理器和授權(quán)聲明集的配置,相當(dāng)?shù)暮?jiǎn)單,現(xiàn)在讓我們來(lái)測(cè)試一下,客戶端代碼如下:

            

  1. UserDataClient client = new UserDataClient();  
  2.             //模擬admin用戶調(diào)用  
  3.             client.ClientCredentials.UserName.UserName = "admin";  
  4.             client.ClientCredentials.UserName.Password = "admin";  
  5.             Console.WriteLine("正在開(kāi)始調(diào)用GetData方法");  
  6.             string msg = client.GetData(100);  
  7.             Console.WriteLine("調(diào)用結(jié)果:{0}", msg);  
  8.             Console.WriteLine("正在開(kāi)始調(diào)用GetUserExtensionXElement方法");  
  9.             XElement xe = client.GetUserExtensionXElement(null);  
  10.             Console.WriteLine("調(diào)用成功,開(kāi)始打印消息.");  
  11.             Console.ForegroundColor = ConsoleColor.Red;  
  12.             Console.WriteLine("==================================");  
  13.             Console.WriteLine(xe.Value);  
  14.             client.Close();  
  15.             //模擬admin2用戶調(diào)用  
  16.             client = new UserDataClient();  
  17.             Console.WriteLine("-----------------------------------------------------------------");  
  18.             client.ClientCredentials.UserName.UserName = "admin2";  
  19.             client.ClientCredentials.UserName.Password = "admin";  
  20.             Console.WriteLine("正在開(kāi)始調(diào)用GetData方法");  
  21.             string msg2 = client.GetData(200);  
  22.             Console.WriteLine("調(diào)用結(jié)果:{0}", msg2);  
  23.             Console.WriteLine("正在開(kāi)始調(diào)用GetUserExtensionXElement方法");  
  24.             XElement xe2 = client.GetUserExtensionXElement(null); 

3、為了讓大家對(duì)服務(wù)器授權(quán)檢查是否成功有一個(gè)具體的認(rèn)識(shí),默認(rèn)情況下,如果授權(quán)不通過(guò),服務(wù)器將拋出一個(gè)SecurityAccessDeniedException異常,告訴客戶端,此調(diào)用未經(jīng)服務(wù)器授權(quán)。我們也捕獲一下,并打印到控制臺(tái):           

  1. XElement xele = null;  
  2.             try  
  3.             {  
  4.                 xele = base.Channel.GetUserExtensionXElement(xe);  
  5.             }  
  6.             catch (SecurityAccessDeniedException ex)  
  7.             {  
  8.                 Console.WriteLine(ex.Message);  
  9.             } 

結(jié)果

1、客戶端調(diào)用

2、服務(wù)器對(duì)客戶端進(jìn)行聲明檢查

3、從上面的結(jié)果可以看出:

我們對(duì)admin用戶授予了對(duì)服務(wù)的兩個(gè)操作的聲明,所以兩個(gè)方法的服務(wù)調(diào)用都通過(guò),

但是admin2用戶只授予了對(duì)服務(wù)的一個(gè)的聲明,所以當(dāng)?shù)谄湔{(diào)用第二個(gè)操作的時(shí)候,授權(quán)未通過(guò)。

從這里可以看出,WCF對(duì)于安全配置提供了非常靈活的方式,讓我們可以隨心所欲的對(duì)服務(wù)訪問(wèn)進(jìn)行授權(quán),但是,并不是所有的安全策略用上,服務(wù)才是安全的,還是那句話,有多大量,吃多大碗飯,別浪費(fèi)了,呵呵~~

博文作者:梁規(guī)曉博客(http://www.cnblogs.com/viter/)!

【編輯推薦】

  1. 使用ASP.NET AJAX調(diào)用WCF服務(wù)項(xiàng)模板
  2. 詳解自定義托管宿主WCF解決方案開(kāi)發(fā)配置過(guò)程
  3. 詳解WCF可擴(kuò)展框架中的行為擴(kuò)展
  4. WCF中通過(guò)Dispose有效實(shí)現(xiàn)重用
  5. WCF開(kāi)發(fā)基礎(chǔ)
責(zé)任編輯:彭凡 來(lái)源: cnblogs
相關(guān)推薦

2009-11-09 16:06:53

WCF自定義集合

2022-11-01 11:15:56

接口策略模式

2010-02-25 16:27:44

WCF擴(kuò)展點(diǎn)

2010-02-25 11:23:29

WCF返回自定義格式

2010-03-01 11:10:41

WCF綁定元素

2010-02-24 14:59:52

WCF自定義過(guò)濾器

2010-03-01 09:56:21

WCF自定義集合類型

2021-08-09 10:31:33

自定義授權(quán)響應(yīng)

2021-07-11 17:17:08

.NET 授權(quán)自定義

2010-03-02 18:01:07

WCF自定義消息篩選器

2009-12-22 11:29:27

WCF自定義集合類型

2022-04-01 15:59:22

SQLPostgreSQL審計(jì)

2021-10-26 10:07:02

鴻蒙HarmonyOS應(yīng)用

2011-08-02 11:17:13

iOS開(kāi)發(fā) View

2022-06-30 14:02:07

鴻蒙開(kāi)發(fā)消息彈窗組件

2022-07-15 16:45:35

slider滑塊組件鴻蒙

2022-06-20 15:43:45

switch開(kāi)關(guān)鴻蒙

2015-02-11 17:49:35

Android源碼自定義控件

2023-08-10 17:14:52

鴻蒙自定義彈窗

2015-02-12 15:33:43

微信SDK
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)