2

我已经实现了服务类,比如说“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 的故事还不错……

4

2 回答 2

0

我会说这完全取决于你想如何设计你的 API,我认为如果你希望你的 API 对来电者,如果我不得不打电话给您的服务,我必须确切地知道您期望您的来电者提出什么样的要求。

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

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

但请记住,如果调用者不拥有此特定声明,他将无法调用该方法。所以这可能是期望的行为,也可能不是。

在一个非常简单的情况下,我只需设计一个带有显式“过滤器”的服务调用,例如

MyService.GetInventoryByReferenceId(string Id)

该契约使调用非常直观,调用者有责任决定如何填充过滤器。

编辑

好的,我并不是说您实施 IDispatchMessageInspector 是错误的,但可能有点矫枉过正,因为您不必要地“嗅探”数据,但您必须进行另一次外部往返才能获得调用者的身份。

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

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

希望能帮助到你,

于 2012-11-20T12:28:11.890 回答
0

更新/解决方案?:

经过一番思考和豪尔赫·阿尔瓦拉多的评论。我决定实施以下事情。

所以...服务类不知道安全上下文。它确实知道有一个属性(枚举)“公司名称”。例如:

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()

这意味着身份提供者应该为客户端令牌提供操作声明。在进行实际调用之前,该声明值正在 IParameterInspector 中进行分析。

4)最后一块 - IInstanceProvider

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

完毕。

我不确定我做对了。但这是我已经做出的解决方案。

于 2012-11-21T16:05:02.203 回答