閱讀703 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[WCF權限控製]基於Windows用戶組的授權方式[下篇]

為了讓讀者對基於Windows用戶組的授權具有深刻的認識,接下來我們通過一個簡單的事例來講解在真正的應用中該授權模式如何使用。對於接下來演示的事例,我們將采用Windows認證和授權。至於授權的最終實現,我們采用的是在服務方法上麵應用PrincipalPermissionAttribute特性方式的聲明式授權。[源代碼從這裏下載]

目錄:
步驟一、創建測試帳號
步驟二、創建服務契約和服務
步驟三、寄宿服務
步驟四、創建客戶端程序

在創建事例解決方案之前我們先完成相應的準備工作,創建兩個測試用的Windows帳號。假設兩個帳號的名稱分別為Foo和Bar,密碼為Password。然後。

我們依然沿用我們再熟悉不過的計算服務的例子,解決方案依然按照如下圖所示的結構來設計。整個解決方式包括四個項目:Contracts、Services、Hosting和Client。對於這樣的結構我們已經了解得夠多了,在這裏沒有必要再贅言敘述了。

clip_image001

在實例解決方案的整個結構建立之後,我們分別在Contracts和Services項目中定義服務契約接口和服務類型。下麵是契約接口ICalculator和服務CalculatorService的定義。而在CalculatorService類的Add方法中應用了PrincipalPermissionAttribute特性,並將Roles屬性設置成了Adminstrators,意味著該服務操作隻能被管理員用戶組中的用戶調用。

ICalculator:

   1: using System.ServiceModel;
   2: namespace Artech.WcfServices.Contracts
   3: {    
   4:     [ServiceContract(Namespace = "https://www.artech.com/")]
   5:     public interface ICalculator
   6:     {
   7:         [OperationContract]
   8:         double Add(double x, double y);
   9:     }   
  10: }

CalculatorService:

   1: using System.Security.Permissions;
   2: using Artech.WcfServices.Contracts;
   3: namespace Artech.WcfServices.Services
   4: {   
   5:     public class CalculatorService : ICalculator
   6:     {
   7:         [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
   8:         public double Add(double x, double y)
   9:         {           
  10:             return x + y;
  11:         }
  12:     }
  13: } 

現在通過Hosting這個控製台程序對上麵創建的服務進行寄宿。下麵給出的是整個寄宿程序的配置。從該配置我們可以看到,服務唯一的終結點采用的綁定類型為WS2007HttpBinding。而在默認的情況下,WS2007HttpBinding采用Message安全模式和Windows認證方式。此外,基於安全主體權限模式的ServiceAuthorization服務行為被應用到了該服務上。

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <system.serviceModel>    
   4:     <services>
   5:       <service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="useWindowsGroupsAuthorization">
   6:         <endpoint address="https://127.0.0.1/calculatorservice" binding="ws2007HttpBinding" 
   7: contract="Artech.WcfServices.Contracts.ICalculator"/>
   8:       </service>
   9:     </services>
  10:     <behaviors>
  11:       <serviceBehaviors>
  12:         <behavior  name="useWindowsGroupsAuthorization">
  13:           <serviceAuthorization principalPermissionMode="UseWindowsGroups"/>
  14:         </behavior>
  15:       </serviceBehaviors>
  16:     </behaviors>
  17:   </system.serviceModel>
  18: </configuration>

而服務寄宿的程序依然簡潔如故,僅僅包括正對寄宿服務類型的ServiceHost的創建和開啟而已。

   1: using System.ServiceModel;
   2: using Artech.WcfServices.Services;
   3: using System;
   4: namespace Artech.WcfServices.Hosting
   5: {
   6:     public class Program
   7:     {
   8:         static void Main(string[] args)
   9:         {
  10:             using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
  11:             {
  12:                 host.Open();
  13:                 Console.Read();
  14:             }
  15:         }
  16:       }
  17:   }

來到整個實例的最後一個步驟,我們將服務調用的客戶程序定義在Client項目中。整個實例演示的目的在於確認針對服務操作Add的授權根據Windows用戶組進行的,我們隻需要關注被授權的服務操作是否被成功調用。為此,我寫了如下一個簡單的輔助性的方法Invoke。如果服務操作被成功執行,輸出“服務調用成功”,如果拋出異常則輸出“服務調用失敗”。

   1: static void Invoke(ICalculator calculator)
   2: {
   3:     try
   4:     {
   5:         calculator.Add(1,2);
   6:         Console.WriteLine("服務調用成功...");
   7:     }
   8:     catch (Exception ex)
   9:     {
  10:         Console.WriteLine("服務調用失敗...");
  11:     }
  12: }

下麵演示了完整的客戶端程序和響應的配置。整個程序體現了兩次針對相同服務操作的調用,而兩次服務調用采用的客戶端憑證分別是基於之前創建的兩個Windows帳號Foo和Bar。

客戶端程序:

   1: using System.Net;
   2: using System.ServiceModel;
   3: using Artech.WcfServices.Contracts;
   4: namespace Artech.WcfServices.Clients
   5: {
   6:     class Program
   7:     {
   8:         static void Main(string[] args)
   9:         {
  10:  
  11:             ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");
  12:             NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;
  13:             credential.UserName = "Foo";
  14:             credential.Password = "Password";
  15:             ICalculator calculator = channelFactory.CreateChannel();
  16:             Invoke(calculator);
  17:  
  18:             channelFactory = new ChannelFactory<ICalculator>("calculatorService");
  19:             credential = channelFactory.Credentials.Windows.ClientCredential;
  20:             credential.UserName = "Bar";
  21:             credential.Password = "Password";
  22:             calculator = channelFactory.CreateChannel();
  23:             Invoke(calculator);
  24:  
  25:             Console.Read();
  26:         }
  27:  
  28:     }
  29: }

配置:

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <system.serviceModel>  
   4:     <client>
   5:       <endpoint name="calculatorService" address="https://127.0.0.1/calculatorservice" binding="ws2007HttpBinding" 
   6: contract="Artech.WcfServices.Contracts.ICalculator"/>
   7:     </client>   
   8:   </system.serviceModel>
   9: </configuration>

由於調用的服務操作需要具有管理員權限采用調用,所以以Foo名義進行調用是沒有為題的,但是對於帳號Bar,由於權限不足將會調用失敗。而客戶端輸出的結果反映了這一點。

   1: 服務調用成功...
   2: 服務調用失敗...

: 對於這個事例演示來說,服務操作隻有具有管理員權限方能被正常調用。雖然我們創建的Windows帳號Foo在管理員用戶組中,但是如果你使用Vista、Windows Server 2008和Windows 7這三種操作係統,在UAC開啟的情況下,即使你以管理員運行我們的演示程序,Foo也不具有管理員權限。所以,你需要關閉UAC采用得到正確的執行結果,否則兩次調用都是輸出“服務調用失敗...”。

[WCF權限控製]基於Windows用戶組的授權方式[上篇]
[WCF權限控製]基於Windows用戶組的授權方式[下篇]


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-26 16:34:07

  上一篇:go  [WCF權限控製]基於Windows用戶組的授權方式[上篇]
  下一篇:go  [WCF權限控製]模擬(Impersonation)與委托(Delegation)[上篇]