简体   繁体   English

如何创建属性以检查用户是否对Identity Core 2.2拥有所有权?

[英]How can I create attribute to check if the user has a claim with Identity core 2.2?

I have an application written with C# on the top on ASP.NET Core 2.2 framework. 我在ASP.NET Core 2.2框架的顶部有一个用C#编写的应用程序。

I want to be able to check if a user has a claim before I allow them access to the action. 我希望能够在允许用户访问该操作之前检查用户是否有索赔。

I created an AuthorizationHandler to check if the user has the claim like so 我创建了一个AuthorizationHandler来检查用户是否有这样的声明

public class ClaimExistanceHandler : AuthorizationHandler<MustHaveClaimRequirement>
    {
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MustHaveClaimRequirement requirement)
        {
            if (context == null
                || context.User == null
                || context.User.Identity == null
                || !context.User.Identity.IsAuthenticated
                || requirement == null
                || string.IsNullOrWhiteSpace(requirement.Type)
                || context.User.HasClaim(requirement.Type, requirement.Value))
            {
                context.Fail();

            }
            else
            {
                context.Succeed(requirement);
            }

            await Task.Yield();
        }
    }
}

then the requirement is as follow 那么要求如下

public class MustHaveClaimRequirement : IAuthorizationRequirement
{
    public string Type { get; set; }
    public string Value { get; set; }

    public MustHaveClaimRequirement(string type, string value)
    {
        Type = type;
        Value = value;
    }
}

But how can I call this requirement as an attribute? 但是,我怎样才能将此要求称为属性? For example HasPermission("do something", "1") 例如HasPermission("do something", "1")

It seems that my HasPermission class needs to implement the AuthorizeAttribute but not sure how would I call the handler from the attribute. 似乎我的HasPermission类需要实现AuthorizeAttribute但不确定如何从该属性调用处理程序。

Your primary goal here is to get the requirement into a policy , and then use or create an attribute that can specify that policy with a string name. 您的主要目标是将需求纳入策略中 ,然后使用或创建可以使用字符串名称指定该策略的属性。 Once you do that, don't need to worry about calling the handler yourself, because ASP.NET Core will take care of that for you. 完成此操作后,无需担心自己调用处理程序,因为ASP.NET Core会为您解决这一问题。

The simplest method of creating policies is to do it on app startup, as documented here . 创建策略的最简单方法是在应用启动时执行此操作,如此处所述 You create your policies, then use AuthorizeAttribute to specify which policy to attach to each endpoint. 创建策略,然后使用AuthorizeAttribute指定要附加到每个端点的策略。

However, doing it this way requires you to define all your policies up front. 但是,以这种方式进行操作需要您预先定义所有策略。 If that would result in you needing to create tons of different policies (because you are going to be checking lots of different claim types), and what you really want is to be able to have an attribute that specifies the claim information, there is a more dynamic way of doing it: see here . 如果那将导致您需要创建大量不同的策略(因为您将要检查许多不同的索赔类型),而您真正想要的是能够拥有一个指定索赔信息的属性,更动态的方式:请参见此处 You need to create an AuthorizeAttribute implementation that stuffs your parameter values (name and type) into a string, and create and register an IAuthorizationPolicyProvider that can interpret that string and generate a policy with the appropriate requirement. 您需要创建一个AuthorizeAttribute实现,该实现将参数值(名称和类型) IAuthorizationPolicyProvider到字符串中,并创建并注册一个IAuthorizationPolicyProvider ,它可以解释该字符串并生成具有适当要求的策略。

EDIT: It's also worth pointing out that ASP.NET Core already includes a requirement implementation for checking a claim: ClaimsAuthorizationRequirement . 编辑:还值得指出的是,ASP.NET Core已经包含了用于检查声明的需求实现: ClaimsAuthorizationRequirement AuthorizationPolicyBuilder has a shortcut for it ( RequireClaim ) so you can quickly create policies that check claims: AuthorizationPolicyBuilder有一个快捷方式( RequireClaim ),因此您可以快速创建检查声明的策略:

services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });

First, you need to register policy and their related claims: 首先,您需要注册保单及其相关声明:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddAuthorization(options =>
    {
        //Scenario 0: Policy requires Claim0 without care what the value is
        options.AddPolicy("MyPolicy0", policy => policy.RequireClaim("Claim0"));

        //Scenario 1: Policy requires Claim1 with value ClaimValue1_1 OR ClaimValue 1_2
        options.AddPolicy("MyPolicy1", policy => policy.RequireClaim("Claim1", "ClaimValue1_1", "ClaimValue1_2"));

        //Scenario 2: Policy requires Claims2 AND Claim3 with particular values
        options.AddPolicy("MyPolicy2", policy => {
            policy.RequireClaim("Claim2", "ClaimValue2");
            policy.RequireClaim("Claim3", "ClaimValue3"));
        }

        //Scenario 3: Policy requires Claims4 OR Claim5 with particular values
        options.AddPolicy("MyPolicy3", policy => {
            policy.RequireAssertion(ctx =>
            {
              return ctx.User.HasClaim("Claim4", "ClaimValue4") ||
                     ctx.User.HasClaim("Claim5", "ClaimValue5");
            })
        }
    });
}

Then apply these checks whenever you need (can be applied at controller or action level): 然后在需要时应用这些检查(可以在控制器或操作级别应用):

[Authorize(Policy = "Policy1")]
public class HomeController : Controller
{

    [Authorize(Policy = "Policy2")]
    public ActionResult MyAction()
    {
       ...
    }

    [Authorize(Policy = "Policy3")]
    public ActionResult MyAnotherAction()
    {
       ...
    }

    [AllowAnonymous]
    public ActionResult NotSecuredAtAll()
    {
       ...
    }
}

Don't forget, if you apply multiple policies to a controller or action, then all policies must pass before access is granted (if only they don't have AllowAnonymous attribute). 别忘了,如果您将多个策略应用于一个控制器或操作,那么所有策略必须在授予访问权限之前通过(如果只有它们没有AllowAnonymous属性)。

More about claims-based authorization in ASP.NET Core 2.2 有关ASP.NET Core 2.2中基于声明的授权的更多信息

I managed to write up the attribute which allows checking for claim existence after taking the feedback from nlawalker and ivamax9 在设法获取nlawalkerivamax9的反馈后,我设法编写了允许检查索赔存在的属性

In conclusion, the HasPermissionAttribute class takes claimType and an optional claimValue then creates a policy name. 总之, HasPermissionAttribute类采用claimType ,然后使用一个可选的claimValue创建一个策略名称。 The attribute class looks like this 属性类如下所示

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class HasPermissionAttribute : AuthorizeAttribute   
{
    public const string Policy_Prefix = "HasClaim";
    public const string Policy_Glue = ".";

    public HasPermissionAttribute(string type, string value = null)
    {
        Policy = GetPolicyValue(type, value);
    }

    private string GetPolicyValue(string type, string value)
    {
        if (string.IsNullOrWhiteSpace(type))
        {
            throw new ArgumentNullException($"{type} cannot be null.");
        }

        List<string> parts = new List<string> { type.Replace(Policy_Glue, "_").Trim() };

        if (!string.IsNullOrWhiteSpace(value))
        {
            parts.Add(value.Replace(Policy_Glue, "_"));
        }

        string policy = $"{Policy_Prefix}{Policy_Glue}{string.Join(Policy_Glue, parts)}";

        return policy;
    }
}

Now that we have a policy being applied via the HasPermissionAttribute we now need to take the applied policy and register it using AuthorizationPolicyBuilder which check if the given claim exists or not. 现在,我们已经通过HasPermissionAttribute应用了策略,我们现在需要采用已应用的策略,并使用AuthorizationPolicyBuilder注册该策略,以检查给定的声明是否存在。 That said, I added a class called ClaimCheckerPolicyProvider which takes the provided claim and processing the check as follow 也就是说,我添加了一个名为ClaimCheckerPolicyProvider的类,该类接受提供的声明并按如下方式处理检查

internal class ClaimCheckerPolicyProvider : IAuthorizationPolicyProvider
{
    public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
    {
        return Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
    }

    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (IsClaimBasePolicy(policyName))
        {
            string[] parts = GetParts(policyName);

            if (parts.Length > 0)
            {
                AuthorizationPolicyBuilder policy = GetPolicyBuilder(parts);

                return Task.FromResult(policy.Build());
            }
        }

        return Task.FromResult<AuthorizationPolicy>(null);
    }

    private bool IsClaimBasePolicy(string policyName)
    {
        return !string.IsNullOrWhiteSpace(policyName)
                        && policyName.StartsWith(HasPermissionAttribute.Policy_Prefix, StringComparison.OrdinalIgnoreCase);
    }

    private string[] GetParts(string policyName)
    {
        return policyName.Split(HasPermissionAttribute.Policy_Glue, StringSplitOptions.RemoveEmptyEntries)
                         .Where(x => !x.Equals(HasPermissionAttribute.Policy_Prefix))
                         .ToArray();
    }

    private AuthorizationPolicyBuilder GetPolicyBuilder(string[] parts)
    {
        if (parts == null)
        {
            throw new ArgumentNullException($"{nameof(parts)} cannot be null.");
        }

        var length = parts.Length;

        if (length == 0)
        {
            throw new ArgumentOutOfRangeException($"{nameof(parts)} cannot cannot be empty.");
        }

        var policy = new AuthorizationPolicyBuilder();

        if (length > 1)
        {
            return policy.RequireClaim(parts[0], parts[1]);
        }

        return policy.RequireClaim(parts[0]);
    }
}

Finally, we need to register the provider as a service. 最后,我们需要将提供程序注册为服务。 In the ConfigureServices of the Startup class, we add the following 在Startup类的ConfigureServices中,添加以下内容

services.AddTransient<IAuthorizationPolicyProvider, ClaimCheckerPolicyProvider>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我无法使用 EF 核心 2.2 加载身份用户 - I can't load Identity User using EF core 2.2 .net核心mvc模拟身份和声明,并测试用户是否有声明 - .net core mvc Mocking Identity and claims and test if user has claim 如何在 .NET Core 2.2 应用程序中创建 CloudTableClient? - How can I create a CloudTableClient in .NET Core 2.2 app? 如何检查API请求中的值声明(ASP.NET Core 2.2) - How to check claim for value in API request (ASP.NET Core 2.2) 如何使用ASP.NET Core Identity v Preview 3.0创建自定义用户和角色? - How i can create custom user and role with ASP.NET Core identity v preview 3.0? ASP.NET 核心。 如何在没有身份用户帐户的情况下创建身份验证 cookie? - ASP.NET Core. How can i create an auth cookie without an identity user account? 如何制作一个可以调用数据库以检查用户声明以授权用户的中间件,在ASP.NET Core 2.2中 - How to make a middleware that can call database to check user claims to authorize a user in asp.net core 2.2 ASP.NET Core 2.2 User.Identity在剃刀中有一个值,但在控制器中没有 - ASP.NET Core 2.2 User.Identity has a value in razor but not in controller 当ASP.NET Core 2.2项目遇到特定异常时,如何重定向用户? - How can I redirect a user when a specific exception is cought with ASP.NET Core 2.2 project? 如何在ASP .Net Core 2.2中为ILoggingBuilder创建配置扩展名? - How can I create configure extension for ILoggingBuilder in ASP .Net Core 2.2?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM