ASP.NET Core 2.1中的策略和声明

时间:2018-08-08 14:47:27

标签: c# asp.net-core

我正在创建一个API,并且对声明/保单有一些疑问。在开发中使用声明注册策略相对容易,我创建了一个带有X声明的策略,并将该策略添加到控制器/方法中,拥有这些声明的任何人都可以访问。问题是:

1)如何在生产环境中创建策略并授予其访问特定位置的权限?这是可能的?还是我唯一要做的就是向用户添加X声明,就足够了吗?

2)在足够的情况下,应该创建一个表来存储声明(仅声明)以具有声明列表,然后将其分配给用户(aspNetUserClaims表)吗?

3)如果我在生产中创建角色并分配声明,然后将该角色分配给用户,是否足以访问上述控制器/方法?还是在登录时明确需要捕获角色声明并将其添加到用户?

提前谢谢!问候!

1 个答案:

答案 0 :(得分:3)

用户访问网站后,该用户就会收到一系列声明。声明属于角色或用户。但是策略是一组规则,它与角色或用户没有任何关系。可以从任何资源(不仅是2个索赔表)中验证策略,它还取决于您的代码。这是基于策略的授权的完整示例:https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.1

  

1)如何在生产环境中创建策略并将其授予   进入某个地方?这是可能的?还是我唯一要做的   向用户添加X声明就足够了吗?

3个问题:是,是,否。

由于Identity Framework中不存在ClaimAuthorizeAttribute,因此您有2个选项:

  1. implement ClaimAuthorizeAttribute: https://github.com/jayway/JayLabs.Owin.OAuthAuthorization/blob/master/src/JayLabs.Owin.OAuthAuthorization/ClaimAuthorizeAttribute.cs

  2. 使用std提出索赔(我建议)。

    Policy

这里是动态应用策略的完整解决方案: https://www.jerriepelser.com/blog/creating-dynamic-authorization-policies-aspnet-core/

  

2)在足够的情况下,应创建一个表来存储声明   (仅声明)具有声明列表,然后将其分配给用户   (aspNetUserClaims表)?

是&否,您应该有表,但是它没有分配给用户,而是存储策略要求的其他地方(在我的以下代码中为public void ConfigureServices(IServiceCollection services) { services.AddAuthorization(options => { options.AddPolicy("EmployeeOnly", policy => { policy.RequireAssertion(context => { //Here you can get many resouces from context, i get a claim here for example var yourvalue = context.User.Claims.FirstOrDefault(x => x.Type == "yourType")?.Value; //here you can access DB or any other API to do anything if you don't mind performance issues. var user = new DefaultContext().AspNetUsers.FirstOrDefaultAsync(x => x.UserName == yourvalue); //return a boolen to end validation. return user != null; }); }); }); } [Authorize(Policy = "EmployeeOnly")] public IActionResult VacationBalance() { return View(); } )。

  

3)如果我在生产中创建角色并分配债权,然后分配   该角色对用户而言,足以访问控制器/   上面提到的方法?或在登录时明确需要   捕获角色的声明并将其添加到用户?

2个问题:是,是。 必须将自定义声明明确分配给用户,以便在登录时使用功能,除非您希望每次需要从数据库访问它。

回到您的第一个问题。

如果您想按条件启用/禁用策略,可以很容易地从AspNetPolicyRequirement开始。

设置:

首先在database中注入IHostingEnvironment

Startup.cs

然后在public class Startup { private readonly IHostingEnvironment _environment; public Startup(IHostingEnvironment environment, ...) { _environment = environment; .... } .... }

中添加以下代码
public void ConfigureServices(IServiceCollection services)

if (_environment.IsProduction())
        {
            services.AddAuthorization(options =>
            {
                options.AddPolicy("AtLeast21", policy =>
                    policy.Requirements.Add(new MinimumAgeRequirement(21)));
            });
        }

下一步:目前没有现有的services.AddAuthorization(options => { if (_environment.IsProduction()) { options.AddPolicy("AtLeast21", policy => policy.Requirements.Add(new MinimumAgeRequirement(21))); } }); AspNetUserPolicy表,而且我认为它不会在框架级别存在。如果您的保单仅来自索赔,没有其他任何保单,则只能使用2个索赔表来注册保单,但我不建议这样做,因为它是WhateverPolicy的反设计。

通常,它可能是以下设计:

Policy

那么您的实体将是:

/****** Object:  Table [dbo].[AspNetPolicy]******/

CREATE TABLE [dbo].[AspNetPolicy](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](150) NOT NULL,
    [Enabled] [bit] NOT NULL,
 CONSTRAINT [PK_AspNetPolicy] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[AspNetPolicyRequirement]******/
CREATE TABLE [dbo].[AspNetPolicyRequirement](
    [Id] [int] NOT NULL,
    [AspNetPolicyId] [int] NOT NULL,
    [RequirementType] [int] NOT NULL,
    [RequirementName] [nvarchar](150) NOT NULL,
    [Enabled] [bit] NOT NULL,
 CONSTRAINT [PK_AspNetPolicyRequirement] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetPolicy] ADD  CONSTRAINT [DF_AspNetPolicy_Enabled]  DEFAULT ((1)) FOR [Enabled]
GO
ALTER TABLE [dbo].[AspNetPolicyRequirement] ADD  CONSTRAINT [DF_AspNetPolicyRequirement_Enabled]  DEFAULT ((1)) FOR [Enabled]
GO
ALTER TABLE [dbo].[AspNetPolicyRequirement]  WITH CHECK ADD  CONSTRAINT [FK_AspNetPolicyRequirement_AspNetPolicy] FOREIGN KEY([AspNetPolicyId])
REFERENCES [dbo].[AspNetPolicy] ([Id])
GO
ALTER TABLE [dbo].[AspNetPolicyRequirement] CHECK CONSTRAINT [FK_AspNetPolicyRequirement_AspNetPolicy]
GO

要通过以下代码启用策略:

public partial class AspNetPolicy
{
    public AspNetPolicy()
    {
        AspNetPolicyRequirement = new HashSet<AspNetPolicyRequirement>();
    }

    public int Id { get; set; }
    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    [Required]
    public bool Enabled { get; set; } = true;

    [InverseProperty("AspNetPolicy")]
    public ICollection<AspNetPolicyRequirement> AspNetPolicyRequirement { get; set; }
}
public partial class AspNetPolicyRequirement
{
    public int Id { get; set; }
    public int AspNetPolicyId { get; set; }
    public RequirementType RequirementType { get; set; }
    [Required]
    [StringLength(150)]
    public string RequirementName { get; set; }
    [Required]
    public bool Enabled { get; set; } = true;

    [ForeignKey("AspNetPolicyId")]
    [InverseProperty("AspNetPolicyRequirement")]
    public AspNetPolicy AspNetPolicy { get; set; }
}
public enum RequirementType
{
    Custom = 0,
    Claim = 1,
    Role = 2,
    UserName = 3,
    AuthenticatedUser = 4,
    Assertion = 5,
}

您必须按照自己的设计完成其余工作。