4

I am looking for some best practices on how to handle the following scenario - flowing permissions from WCF service layer through to UI:

I have WCF services with methods that have been decorated with the PrincipalPermission attribute. I would like a means to allow a client to check if they have the required permissions before invoking the method.

A basic example of this could be checking whether a user can perform a specific function (say submitting an order), which can then be used to enable/disable a button within the UI.

Possible options are to add "chatty" operations like bool CanSubmitOrder() to the service, or instead have a single method OrderServicePermissions GetPermissions() which returns a message with a property CanSubmitOrder? I can then set the enabled state of a "Submit Order" button to the result.

So does anybody know of a better approach, or even a best practice?

Thanks in advance!

4

3 回答 3

0

在服务调用中具有PrincipalPermission属性的全部意义在于,您不必提前检查调用者是否有权调用 - 如果他没有,WCF 运行时将抛出异常。

为什么不只依赖这个内置机制呢?为什么不将您的服务调用放在 try..catch 块中并在异常确实发生时处理它们?无论如何,这应该是“例外”情况,对吧?

除了您所描述的之外,我没有看到任何其他“神奇”方式。但普遍接受的做法是调用并处理任何发生的异常。

马克

于 2009-09-25T16:38:51.660 回答
0

好吧,如果您能够改进您的应用程序以使用 Windows Identity Foundation (WIF) 来保护您的服务,您可以使用 RequestSecurityTokenResponse 的 DisplayToken 属性来实现这一点。

http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.protocols.wstrust.requestsecuritytokenresponse.requesteddisplaytoken.aspx

假设您的安全令牌服务支持它,显示令牌可能包含一个声明集,允许您将权限流入 UI,例如禁用绑定到用户无法调用的服务的控件。显示令牌是为 CardSpace 实现的 WS-Trust 的扩展,因此它不太可能在 Windows 世界之外得到广泛支持。

但请注意,有些人认为显示令牌是坏消息并且违反了第一定律:

http://www.francisshanahan.com

而其他人则认为这是对一个常见问题的合理而务实的解决方案:

http://blogs.msdn.com/b/vbertocci/archive/2007/10/31/on-displaytoken.aspx

于 2011-10-11T19:53:29.480 回答
0

有两种通用类型来实现检查逻辑:

  1. 共享库。示例是“RIA 服务 + Silverlight”。

    优点:易于实施。

    缺点:没有互操作性(仅限 .NET);每次库更改都需要客户端更新。

  2. 在服务部分实现通用方法验证。 优点:互操作性,如果检查逻辑发生变化,无需客户端更新

    缺点:可能很复杂,因为它只在你身上

如果我们使用 SOA,最好使用第二选择,前提是您不是仅在您的公司中使用应用程序,而 .NET 无处不在。

例子

让我们考虑一个常见的例子。我们有一个 windows/wpf 表单。并且有两个字段:字符串类型的“姓”,int类型的“年龄”;和一个“保存”按钮。我们需要在客户端进行一些检查

1) 对于某些用户,“保存”按钮被禁用;

2)姓氏不能为空,最大长度为256;

3)年龄不能小于0;

调用保存方法是

void Save(string surname, int age);

在服务中创建第二个方法,该方法返回带有验证信息的 PermissonAnswerDTO 对象类型;

PermissonAnswerDTO SaveValidate(string surname, int age);

和主要验证方法

// If arguments are wrong
        [FaultContract(typeof(NotSupportedException))]
        // If the user have permisson to invoke this method
        [FaultContract(typeof(CustomNotEnoughPermission))]
        PermissonAnswerDTO Validate(string methodName, object[] methodParams);

验证。

Validate("SaveValidate", null)在窗口加载时调用。如果抛出 CustomNotEnoughPermission 类型的异常,那么我们会阻止“保存”按钮。

如果用户可以保存,则调用用户的数据Validate("SaveValidate", object[2]{"Surname", "-60"};。-60 无效,因此我们得到 PermissonAnswerDTO 类型的答案对象,其中包含以下信息:

ParameterName: "age",
ExceptionMessage: "age cannot be less then null".

我们可以优雅地向用户展示这些信息。


我对此的想法是,有一天微软会实现这一点,并像往常一样调用新技术。大多数情况下,微软的技术并没有宣传的那么具有革命性。例如 Windows Identity Foundation 和 Reactive Extensions。

完整示例

[DataContract]
    public class ParameterExceptionExplanaitonDTO
    {
        [DataMember]
        public string ParameterName;
        [DataMember]
        public string ExceptionMessage;
    }

[DataContract]
public class PermissonAnswerDTO
{
    [DataMember]
    public bool IsValid;

    [DataMember]
    public ParameterExceptionExplanaitonDTO[] ParameterExceptions;
}

public class Service1 : WcfContracts.IService1
{
    // If arguments are wrong
    [FaultContract(typeof(NotSupportedException))]
    // If the user have permisson to invoke this method
    [FaultContract(typeof(CustomNotEnoughPermission))]
    public PermissonAnswerDTO Validate(string methodName, object[] methodParams)
    {
        //1) Using Reflection find the method with name = <methodName + Validate>
        //2) Using Reflection cast each object in "object[] methodParams" to the required type
        //3) Invoke method
    }

    private PermissonAnswerDTO GetUserNameValidate(int id)
    {
        //logic to check param
    }

    public string GetUserName(int id) 
    {
        // if the user calls method we need validate parameter
        GetUserNameValidate(id);

        //some logic to retreive name
    }
}
于 2012-04-08T12:26:36.857 回答