C# 为什么未调用ClaimsAuthorizationManager.LoadCustomConfiguration?

C# 为什么未调用ClaimsAuthorizationManager.LoadCustomConfiguration?,c#,configuration,authorization,claims-based-identity,claims,C#,Configuration,Authorization,Claims Based Identity,Claims,我正在尝试实现我自己的ClaimsAuthorizationManager,主要遵循MSDN上的示例。目标是从项目配置文件加载策略,并使用它们评估应用程序发出的访问控制请求 我的自定义ClaimsAuthorizationManager与下面的代码非常相似 当我运行TestSuite来测试CheckAccess()方法时,它失败了。我调试并注意到管理器没有从配置文件加载策略事实上,LoadCustomConfiguration()方法从未被调用,即使我在配置中注册了自定义管理器。这是什么原因 我

我正在尝试实现我自己的
ClaimsAuthorizationManager
,主要遵循MSDN上的示例。目标是从项目配置文件加载策略,并使用它们评估应用程序发出的访问控制请求

我的自定义
ClaimsAuthorizationManager
与下面的代码非常相似

当我运行TestSuite来测试
CheckAccess()
方法时,它失败了。我调试并注意到管理器没有从配置文件加载策略事实上,
LoadCustomConfiguration()
方法从未被调用,即使我在配置中注册了自定义管理器。
这是什么原因

我正试图在一个TestProject中对此进行测试,其中我的App.config如下所示:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!--WIF 4.5 sections -->
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  </configSections>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /></startup>

<system.identityModel>
    <identityConfiguration>
      <claimsAuthorizationManager type="Foo.Bar.ClaimsAuthorization.FooBarAuthorizationManager, Foo.Bar.ClaimsAuthorization">
        <policy resource="TestResource" action="TestAction">
          <or>
            <claim claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" claimValue="Developer" />
            <claim claimType="http://schemas.xmlsoap.org/claims/Group" claimValue="Administrator" />
          </or>
        </policy>
      </claimsAuthorizationManager>
    </identityConfiguration>
</system.identityModel>
</configuration>
var hasAccess = ClaimsAuthorization.CheckAccess("TestAction", "TestResource");
Assert.IsFalse(hasAccess);

我意识到我的设置是正确的,但我以错误的方式调用了自定义
ClaimsAuthorizationManager

因为我自己(错误地)初始化了AuthorizationManager,而不是使用系统基于配置创建的AuthorizationManager,所以我绕过了整个“LoadCustomConfiguration()”部分

解决方案是调用系统在启动时创建的ClaimsAuthorizationManager。

我真的不知道如何从TestSuite环境(即不是从ASP.NET)正确调用它,但我发现了这个有用的包,它可以轻松访问当前有效的ClaimsAuthorizationManager:

namespace Foo.Bar.ClaimsAuthorization
{
    public class FooBarAuthorizationManager : ClaimsAuthorizationManager
    {
        static readonly Dictionary<ResourceAction, Func<ClaimsPrincipal, bool>> Policies = new Dictionary<ResourceAction, Func<ClaimsPrincipal, bool>>();
        readonly PolicyReader policyReader = new PolicyReader();

        /// <summary> 
        /// Overloads  the base class method to load the custom policies from the config file 
        /// </summary> 
        /// <param name="nodelist">XmlNodeList containing the policy information read from the config file</param>
        public override void LoadCustomConfiguration(XmlNodeList nodelist)
        {
            if (nodelist == null) 
                return;
            foreach (XmlNode node in nodelist)
            {
                // 
                // Initialize the policy cache 
                //
                XmlDictionaryReader rdr = XmlDictionaryReader.CreateDictionaryReader(new XmlTextReader(new StringReader(node.OuterXml)));
                rdr.MoveToContent();

                string resource = rdr.GetAttribute("resource");
                string action = rdr.GetAttribute("action");

                Expression<Func<ClaimsPrincipal, bool>> policyExpression = policyReader.ReadPolicy(rdr);

                // 
                // Compile the policy expression into a function 
                //
                Func<ClaimsPrincipal, bool> policy = policyExpression.Compile();

                // 
                // Insert the policy function into the policy cache 
                //
                Policies[new ResourceAction(resource, action)] = policy;
            }
        }

        /// <summary>
        /// Checks if the principal specified in the authorization context is authorized to perform action specified in the authorization context 
        /// on the specified resoure
        /// </summary>
        /// <param name="pec">Authorization context</param>
        /// <returns>true if authorized, false otherwise</returns>
        public override bool CheckAccess(AuthorizationContext pec)
        {
            //
            // Evaluate the policy against the claims of the 
            // principal to determine access
            //
            bool access;
            try
            {
                var ra = new ResourceAction(pec.Resource.First().Value, pec.Action.First().Value);

                access = Policies[ra](pec.Principal);
            }
            catch (Exception)
            {
                access = false;
            }

            return access;
        }

        public bool CheckAccess(string resource, string action)
        {
            return CheckAccess(resource, action, Thread.CurrentPrincipal);
        }

        public bool CheckAccess(string resource, string action, IPrincipal principal)
        {
            var claimsPrincipal = principal as ClaimsPrincipal;
            if (claimsPrincipal == null)
                throw new ArgumentException("Principal is null or not of type ClaimsPrincipal!", "principal");
            var context = new AuthorizationContext(claimsPrincipal, resource, action);

            return CheckAccess(context);
        }
    }
}

现在我可以简单地这样称呼它:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!--WIF 4.5 sections -->
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  </configSections>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /></startup>

<system.identityModel>
    <identityConfiguration>
      <claimsAuthorizationManager type="Foo.Bar.ClaimsAuthorization.FooBarAuthorizationManager, Foo.Bar.ClaimsAuthorization">
        <policy resource="TestResource" action="TestAction">
          <or>
            <claim claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" claimValue="Developer" />
            <claim claimType="http://schemas.xmlsoap.org/claims/Group" claimValue="Administrator" />
          </or>
        </policy>
      </claimsAuthorizationManager>
    </identityConfiguration>
</system.identityModel>
</configuration>
var hasAccess = ClaimsAuthorization.CheckAccess("TestAction", "TestResource");
Assert.IsFalse(hasAccess);
更新:
反编译源代码显示,这是

FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager

这似乎是访问当前的
ClaimsAuthorizationManager

Doh的正确方法,我刚刚意识到我可能不应该自己创建authManager。我不知道如何调用CheckAccess。我正在尝试构建您上面提供的代码。您能告诉我在哪个命名空间中找到“PolicyReader”类吗?我尝试过在MSDN上搜索,但唯一的参考是一个密封的嵌套类。它在中,这里是直接下载链接:对我来说,使用注册的ClaimsAuthorizationManager的这种方式也很有效:
ClaimsPrincipalPermission.CheckAccess(“TestResource”,“TestAction”)