2008-09-28 124 views
7

我正在實施一個安全的WCF服務。身份驗證是使用用戶名/密碼或Windows憑據完成的。該服務託管在Windows服務進程中。現在,我試圖找出爲每個服務操作實施授權的最佳方式。WCF服務授權碼

例如,請考慮以下方法:

public EntityInfo GetEntityInfo(string entityId); 

正如你可能知道,在WCF中,有一個的OperationContext對象,從中可以獲取調用者/客戶端傳遞的安全證書。現在,在調用方法的第一行時,認證已經完成。但是,如果決策取決於輸入數據本身,我們如何實現授權?例如,在上述情況下,說'管理員'的用戶(其權限等存儲在數據庫中),允許獲取實體信息,其他用戶不應該被允許...我們在哪裏進行授權檢查?

說我們把它放在方法的第一行,像這樣:

CheckAccessPermission(PermissionType.GetEntity, user, entityId) //user is pulled from the current OperationContext 

現在,有幾個問題:

  1. 難道我們驗證ENTITYID(例如檢查空值/空值等)在授權檢查之前或在授權檢查內?換句話說,如果授權檢查應該包含在每個方法中,那麼這是一個好的模式嗎?哪一個應該首先發生 - 參數驗證或授權?

  2. 當授權檢查遍佈此地時,我們如何單元測試WCF服務,並且我們在單元測試中沒有OperationContext!? (假設我試圖直接測試這個服務類的實現,沒有任何WCF設置)。

任何想法傢伙?

回答

3

對於問題1,絕對先做授權。在授權之前不應執行任何代碼(在您的控制範圍內)以維持最嚴密的安全。保羅上面的例子非常好。

對於問題2,您可以通過繼承具體的服務實現來處理此問題。如上所述,將真正的業務邏輯實現爲具有抽象的「CheckPermissions」方法的抽象類。然後創建2個子類,一個用於WCF使用,另一個(在非部署DLL中非常孤立)返回true(或者您希望它在單元測試中執行的任何操作)。

示例(注意,這些不應該在同一個文件或甚至DLL中!):

public abstract class MyServiceImpl 
{ 
    public void MyMethod(string entityId) 
    { 
     CheckPermissions(entityId); 
     //move along... 
    } 
    protected abstract bool CheckPermissions(string entityId); 
} 

public class MyServiceUnitTest 
{ 
    private bool CheckPermissions(string entityId) 
    { 
     return true; 
    } 
} 

public class MyServiceMyAuth 
{ 
    private bool CheckPermissions(string entityId) 
    { 
     //do some custom authentication 
     return true; 
    } 
} 

然後,您的WCF部署使用類「MyServiceMyAuth」,然後對其他單元進行測試。

6

對於問題1,最好先執行授權。這樣,您就不會將驗證錯誤消息泄露給未經授權的用戶。與其使用本土化的認證方法(我假設您的CheckAccessPermission是什麼)不同,您可能可以連接到WCF對ASP.NET角色提供程序的開箱即用支持,而不是使用自己的CheckAccessPermission。一旦完成,您可以通過OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.IsInRole()執行授權。 PrimaryIdentity是一個IPrincipal。

+0

謝謝保羅。與第一次做授權,問題是這樣的: 我們如何授權用戶如果我們需要檢查基於輸入參數的權限?在我們使用它進行授權之前,我們不需要首先驗證這些論據嗎? – Krishna 2008-09-28 03:52:39

6

關於問題#2,我會做這個使用依賴注入和建立這樣的服務實現的東西:

class MyService : IMyService 
{ 
    public MyService() : this(new UserAuthorization()) { } 
    public MyService(IAuthorization auth) { _auth = auth; } 

    private IAuthorization _auth; 

    public EntityInfo GetEntityInfo(string entityId) 
    { 
      _auth.CheckAccessPermission(PermissionType.GetEntity, 
        user, entityId); 

      //Get the entity info 
    } 
} 

注意IAuthorization是,你會定義一個接口。

因爲你將要測試的直接服務類型(即,不運行它的WCF託管框架內),你只需設置你的服務,使用一個虛擬IAuthorization類型,允許所有呼叫。然而,甚至更好的測試是模擬IAuthorization,並測試它在您期望的參數時和之後被調用。這使您可以測試對授權方法的調用是否有效,以及方法本身。

分離授權到它自己的類型也可以讓你更方便地測試,這是孤立正確的。在我的(儘管有限)的經驗,使用DI「模式」給你的關注和可測試性在你的類型好得多的分離,以及導致一個更清潔的界面(這顯然是公開辯論)。

我的首選模擬框架是RhinoMocks它是免費的,有非常好的流暢的界面,但也有很多人在那裏的。如果您想了解更多關於DI這裏有一些很好的引物和.Net框架: