[WCF許可權控制]基於Windows使用者組的授權方式[上篇]

行者武松發表於2017-10-26

Windows使用者組安全主體許可權模式,顧名思義,就是將利用Windows安全系統將對應的Windows帳號所在的使用者組作為該使用者許可權集的授權方式。認證和授權密不可分,但是對於認證和授權在WCF安全體系中的實現來說,它們則是相對獨立的。認證屬於安全傳輸的範疇,是在通道層實現的,而授權則是在服務模型層實現的。但是對於基於Windows使用者組的授權來說,最終體現出來的授權行為卻和採用何種認證具有密切的關係。

一、Windows使用者組授權與認證的關係

無論是對於基於Windows使用者組還是基於ASP.NET Roles提供程式的授權,最終都體現在建立相應的安全主體,並將其附加到當前執行緒上。對於Windows使用者組模式來說,有一點是肯定的:不論採用何種客戶端憑證型別以及認證模式,最終建立的安全主體都是一個WindowsPrincipal,並且這個WindowsPrincipal對應的安全身份是一個WindowsIdentity。但是該WindowsPrincipal的Identity能否正確地反映被認證後的使用者,以及其本身能夠正確反映該認證使用者的許可權,就和認證有密切的關係。

具體來說,當你選擇了Windows使用者組安全主體許可權模式,只有在採用Windows認證的情況下最終生成的安全主體才能正確地反映被認證的使用者。這裡的Windows認證包括如下三種情況:

  • 客戶端憑證為Windows憑證;
  • 客戶端憑證為使用者名稱/密碼憑證,並採用Windows認證模式;
  • 客戶端憑證為X.509證書憑證,並允許與Windows帳號進行對映。

在其他情況下,最終被建立的是一個“空”的WindowsPrincipal。這個空的WindowsPrincipal不僅僅體現在具有一個“空”的許可權集,而且其內部的WindowsIdentity也為“空”。該WindowsIdentity具有如下面列表所示的屬性。

  • Name:空字串
  • AuthenticationType: 空字串
  • IsAuthenticated:False
  • Groups:Null
  • IsAnonymous:True
  • IsGuest:False
  • IsSystem:False

在非Windows認證的情況下,即使存在著一個與認證使用者一致的Windows帳號,WCF授權系統都不會基於該Windows帳號來建立最終的WindowsPrincipal。舉個例子,假設服務寄宿端所在的域中具有一個使用者叫做“張三”,並且存在於當前機器的管理員(Administrators)使用者組中。現在我們對某個服務操作進行授權,要求必須在具有管理員許可權才能被呼叫。在進行服務寄宿的時候,終結點的繫結採用使用者名稱/密碼作為客戶端憑證,並選擇Membership認證模式。在認證成功的情況下,被授權的服務操作也是不能被正常呼叫的。

通過前面一篇文章的介紹,我們知道了WCF採用怎樣的授權的方式通過ServiceAuthorizationBehavior這一服務行為來控制。所以針對授權的程式設計主要就體現在對該服務行為的設定。對於Windows使用者組授權來說,我們只需要將ServiceAuthorizationBehavior的PrincipalPermissionMode屬性設定成PrincipalPermissionMode.UseWindowsGroups即可。

二、ServiceAuthorizationBehavior服務行為的設定

既然ServiceAuthorizationBehavior是一個服務行為,我們只需要通過程式設計或者配置的方式將該服務行為新增到當前服務的行為列表中就可以了。你可以按照下面的程式設計方式讓寄宿的服務採用基於Windows使用者組授權模式。

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {
   3:     ServiceAuthorizationBehavior behavior = host.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
   4:     if (null == behavior)
   5:     {
   6:         behavior = new ServiceAuthorizationBehavior();
   7:         host.Description.Behaviors.Add(behavior);
   8:     }
   9:     behavior.PrincipalPermissionMode = PrincipalPermissionMode.UseWindowsGroups;
  10:     host.Open();
  11:     //...
  12: }

此外在ServiceHost你也可以通過ServiceHost的只讀屬性Authorization得到這個ServiceAuthorizationBehavior物件。如下面的程式碼片斷所示,該屬性實際上是定義在ServiceHost的基類ServiceHostBase中。

   1: public abstract class ServiceHostBase
   2: {
   3:     //其他成員
   4:     public ServiceAuthorizationBehavior Authorization { get; }
   5: }

在讀取該屬性的時候,如果當前服務描述中的服務行為列表中找不到ServiceAuthorizationBehavior,系統會自動建立一個ServiceAuthorizationBehavior物件並新增到服務行為列表中。所以對於上面的這段服務寄宿程式碼實際和下面是完全等效的。

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {    
   3:     host.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.UseWindowsGroups;
   4:     host.Open();
   5:     //...
   6: }

我們依然推薦採用配置的方式進行授權模式的設定。而下面一段配置和上面的程式碼在作用上是等效的。

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

為了讓讀者對基於Windows使用者組的授權具有深刻的認識,在《下篇》中我們通過一個簡單的事例來講解在真正的應用中該授權模式如何使用。

[WCF許可權控制]基於Windows使用者組的授權方式[上篇]

[WCF許可權控制]基於Windows使用者組的授權方式[下篇]

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


相關文章