在类级别和方法级别应用ClaimsPrincipalPermissionAttribute时出现异常

时间:2013-11-01 15:43:23

标签: c# .net wif claims-based-identity code-access-security

我有一个用ClaimsPrincipalPermissionsAttribute装饰的课程。该类有一个方法,也用ClaimsPrincipalPermissionsAttribute装饰。我的期望是:

首先,当我实例化该类时,我会调用我的自定义ClaimsAuthorizationManager。这可以按预期工作。

其次,当我调用该方法时,我会收到两次对ClaimsAuthorizationManager的调用。一个是类级别属性的资源和操作,另一个是方法级别属性。这不起作用。相反,当我调用方法时,我会抛出SecurityException。异常消息是:

  

解码嵌入式权限集对象失败。

为了尝试查看发生的情况,我通过复制ClaimsPrincipalPermissionsAttribute中的代码创建了自定义属性。我可以看到在我的属性上调用了CreatePermission()方法并且它成功返回了ClaimsPrincipalPermission,但是在调用ClaimsAuthorizationManager之前抛出了异常。

我的代码如下所示:

using System;
using System.IdentityModel.Services;
using System.Security.Permissions;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new SecuredClass();

            test.MethodLevelSecuredMethod();

            Console.ReadKey();
        }
    }

    [ClaimsPrincipalPermission(SecurityAction.Demand, Resource = "SecuredClass", Operation = "GeneralAccess")]
    class SecuredClass
    {
        [ClaimsPrincipalPermission(SecurityAction.Demand, Resource = "MethodLevelSecuredMethod", Operation = "Call")]
        public void MethodLevelSecuredMethod()
        {
            Console.WriteLine("Called MethodLevelSecuredMethod");
        }
    }
}

我做错了什么?是否可以在类和方法级别声明属性?

我正在使用.Net 4.5。

2 个答案:

答案 0 :(得分:3)

问题出现是因为ClaimsPrincipalPermission没有实现采用PermissionState参数的公共构造函数。 (http://msdn.microsoft.com/en-us/library/vstudio/yaah0wb2.aspx记录了对此的需求,尽管隐藏在文本的中间。)

这实际上是框架中的一个错误,可能应该在https://connect.microsoft.com/visualstudio/feedback报告。如果你这样做,你可能想要添加一个FxCop规则来检查这个构造函数是否存在也是一个好主意。

在修复错误之前,如果您想使用声明式方法进行基于声明的授权,那么您唯一真正的选择是重新实施ClaimsPrincipalPermissionClaimsPrincipalPermissionAttribute

答案 1 :(得分:0)

我通过在类构造函数中使用CheckAccess调用来解决这个问题:

class SecuredClass
{
    public SecuredClass()
    {
        ClaimsPrincipalPermission.CheckAccess("SecuredClass", "GeneralAccess");
    }

    [ClaimsPrincipalPermission(SecurityAction.Demand, Resource = "MethodLevelSecuredMethod", Operation = "Call")]
    public void MethodLevelSecuredMethod()
    {
        Console.WriteLine("Called MethodLevelSecuredMethod");
    }
}