DataContext根据授权声明而更改

时间:2012-11-20 12:13:41

标签: c# wcf

我已经实现了Service类,让我们说“DataSourceService”。现在我想通过WCF公开它并使其成为REST。没有问题,这可以在WCF中轻松完成。

但是,我会说,架构问题。

所以我想说我有一个方法:

 IEnumerable<string> ReadAllInventoryItems()

根据用户授权声明(角色或权限等),我必须返回IEnumerable<string>的问题。 我可以通过在DataSourceService的每个方法中验证这些声明来做到这一点。 这样的事情:

IEnumerable<string> ReadAllInventoryItems()
{
     var companyName = ReadCompanyNameFromAuthorisationContext();
     var items = ReadAll().Where( i => i.CompanyName == companyName).ToList();
     return Items;
}

我想说这种方法存在一个大问题。 即:没有此“声明”上下文,DataSourceService变得不可用。 当我在没有WCF的情况下使用它时,我必须为每个调用准备Claims或UserIdentity上下文。

所以对我来说下一步是“考虑WCF IDispatchMessageInspector”但后来我意识到我必须实现一个IDispatchMessageInspector和一个OperationInvoker然后我可以使用某种带权限的属性来装饰Web服务方法(这个属性将被使用)稍后在OperationInvoker中。)

最后我会得到:

    [AuthorizationFiltering]
    IEnumerable<string> ReadAllInventoryItems()
    {         
         var items = ReadAll().Where( i => i.CompanyName == companyName).ToList();
         return Items;
    }

你怎么看?

我是否应该坚持“在DataSourceService的每个方法中验证这些声明” 或WCF IDispatchMessageInspector,MethodInvoker故事并不是那么糟糕......

2 个答案:

答案 0 :(得分:0)

我想说这一切都取决于你想要如何设计你的API,我认为如果你希望你的API是公开的,那么在你的授权上下文中模糊“过滤器”(比如在你的声明中)并不是一个好主意。对于来电者而言,如果我不得不打电话给您的服务,我必须确切地知道您对来电者的期望是什么类型。

但是,如果您的所有来电者都知道您使用的是基于声明的授权,那么您可以将您的方法设计为“要求”某些声明,那么您的方法就可以了。你可以使用类似的东西:

[PrincipalPermission(SecurityAction.Demand, Role = ManagersWithInventory)]

请记住,如果来电者不具备此特定声明,他将无法调用该方法。所以这可能是所希望的行为。

在一个非常简单的例子中,我只是设计一个带有明确的“过滤器”的服务调用,如

MyService.GetInventoryByReferenceId(string Id)

该合同使调用非常直观,并且调用者有责任决定如何填充过滤器。

修改

好吧,我不是说你的实现IDispatchMessageInspector是错误的,但可能有点过分,因为你不必要地“嗅探”数据,但你必须进行另一次外部往返以获得调用者的身份。

我认为更好的方法是使用“真实”声明身份:双方使用Microsoft.IdentityModel.dll并使用声明透明地让WCF使用它传输凭据。

有一点需要注意的是,您的旧桌面应用程序调用您的服务仍然可以工作,因为WIF将以前的IIdentity包装在IClaimsIdentity中,因此您甚至可以使用或不使用声明的“用户”(在您的服务端)< / p>

希望它有所帮助,

答案 1 :(得分:0)

更新/解决方案?:

经过一番思考和Jorge Alvarado的评论。我决定实施以下内容。

所以... Service类不了解安全上下文。 它确实知道有一个属性(枚举)“CompanyName”。 对于实例:

public ClientEnumerationType? CurrentClient { get; set; }

当我服务想要从ReadInventory函数返回结果时,我有以下代码:

IEnumerable<string> ReadAllInventoryItems()
{
     var items = ReadAll();

     return CurrentClient.HasValue ? FilterByClient(items, urrentClient.Value).ToList() : items;
}

因此,该实现允许我在WCF之外使用该类而没有任何问题。

WCF怎么样? 我正在考虑从WCF到底需要什么,实际上我只需要一件事。授权客户端,实例化服务类并设置值CurrentClient属性。

为了实现这一点,我实施了几项。

1)IEndpointBehavior

我需要它为每个合约方法安装Message Inspector和InstanceProvider以及ParameterInspectors。

2)IDispatchMessageInspector

获取WCF消息,从请求中提取令牌,验证令牌并将Thread.CurrentPrincipal设置为来自请求的所有声明值的ClaimsPrincipal。

第3)IParameterInspector

我需要它来验证合同中每个方法的Claim = Action。 对于实例我有:

    [OperationContract]
    [ClaimActionRequred(Action = "read")]        
    IEnumerable<string> ReadAllInventoryItems()

这意味着I Identity Provider应为客户端令牌提供Action声明。 在进行实际调用之前,正在IParameterInspector中分析该声明值。

4)最后一块 - IInstanceProvider

我需要的是,实例化ServiceClass并根据声明值传递CurrentClient属性值。

完成。

我不确定我做得对。但这是我已经做过的事情。