基于ASP.NET Core自定义策略的授权-不清楚 [英] ASP.NET Core Custom Policy Based Authorization - unclear

查看:68
本文介绍了基于ASP.NET Core自定义策略的授权-不清楚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

OK,ASP.NET Core中基于自定义策略的授权.我有点了解这个新的身份框架的想法,但是仍然不能100%清楚您可以用此框架实现什么.假设我们在HomeController中有一个名为List的Action.此操作将查询并显示数据库中的产品列表.必须访问此列表的用户必须是Marketing部门的一部分.因此,在我们的政策中,我们检查用户是否有一个名为Division的索赔,并且该索赔的价值是Marketing.如果是,那么他将被允许查看该列表,否则将不会被查看.我们可以这样装饰动作:

OK, Custom Policy Based Authorization in ASP.NET Core. I kinda of understood the idea of this new identity framework, but still not 100% clear what you can achieve with this. Assuming we have an Action in HomeController called List. This action will query and display a list of products from the database. The users that must access this list must be part of the Marketing division. Therefore in our policy we check if user has a claim called Division and the value of that is Marketing. If yes then he will be allowed to see the list otherwise not. We can decorate our action like this:

[Authorize(Policy = "ProductsAccess")]
public IActionResult List()  
{
    //do query and return the products view model
    return View();
}

这一切都很好.它将完美运行.

All good with this. It will work perfectly.

方案1:如果我想在产品级别添加策略,并且基于该策略,用户将只能看到其部门的产品.因此,营销人员将看到他的产品,而R& D将看到他的产品,依此类推.我该如何实现?可以通过政策来完成吗?如果是,怎么办?

Scenario 1: What if I want to add the policy at the product level, and based on the policy the user will see only the products from his division. So marketing guy will see his products, R&D will see his and so forth. How can I achieve that? Can it be done with a policy? If yes how?

方案2:那么在现场级别的访问又如何呢?假设我想隐藏某些字段?例如:所有产品都将具有某些列,这些列必须对管理者可见并且对其他用户隐藏?可以使用自定义策略来完成此操作吗?如果是,怎么办?

Scenario 2: What about access at the field level? Let's say maybe I want to hide certain fields? Example: all products will have certain columns that must be visible to Managers and hidden to the rest of users? Can this be done using custom policies? If yes how?

推荐答案

对于方案1 ,您可以使用本质上,您将IAuthorizationService注入到服务或控制器中,然后具有一个或多个授权处理程序,这些处理程序派生出AuthorizationHandler<TRequirement, TDocument>形式,然后调用

In essence, you'd inject IAuthorizationService into your service or controller, then and have one or more authorization handlers which derive form AuthorizationHandler<TRequirement, TDocument> and then call

if(await _authorizationService.AuthorizeAsync(User, document, "MyPolicy"))
{
    // Success, user has access to it
}

缺点:您必须从数据库中获取所有产品,然后在内存中进行过滤,因此它对于不需要分页的单个文档或较小的数据非常适用.即使使用较小的数据,分页也会破坏它(即,如果您请求50个产品,但是用户无权访问其中40个产品,则尽管页面大小为50,也只会返回10个产品).

Downside: You have to fetch all products from database, then filter in memory, so it will work well for single documents or smaller data, where you don't need pagination. Pagination will break it, even on smaller data (i.e. if you request 50 products, but user don't have access to 40 of them, only 10 will be returned, despite the page size being 50).

对于EF Core 2.0(如果您将EF Core用作ORM),则可以选择另一种方法.您可以添加全局过滤器,该过滤器将应用于对特定实体的所有查询.

an alternative will be possible with EF Core 2.0 (that's if you use EF Core as your ORM). You can add global filters, which will applied to all queries to a certain entity.

有关更多信息,请参见实体框架核心2.0公告博客文章:

For more information, see Entity Framework Core 2.0 Announcement blog post:

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    public int TenantId {get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasQueryFilter(p => !p.IsDeleted &&
                  p.TenantId == this.TenantId );
    }
}

它是否适合您的情况,取决于您是否可以使用行级数据(即某种资源所有者"字段).

It may or may not be suitable for your case, it depends if you have a row-level data you can use (i.e. some kind of "resource owner" field).

场景2 不可能与Identity一起使用,您必须自己实现一些功能,但这是一个非常复杂的主题(如果您曾经工作过,有了Dynamics CRM,您就会明白我的意思.

Scenario 2 isn't possible out of the box with Identity as far as I know, you'd have to implement something on your own, but it's a very complex topic (if you ever worked with Dynamics CRM, you know what I mean).

更新

只是为了快速实施,您可以尝试将响应包装在ExpandoObject周围(这是使用dynamic关键字时所使用的基础),并对其进行迭代,从而删除用户无权访问的属性在从控制器操作中将其返回之前,或编写一个授权过滤器,该过滤器将自动对特定或所有控制器执行此操作.

Just for an quick implementation, you can try to wrap your response around an ExpandoObject (that's what's used underlying when you use dynamic keyword) and the iterate over it, removing properties the user doesn't have access to before returning it from the controller action or write an Authorization filter, which will automatically do that for specific or all controllers.

有关(如何构造/使用expando对象的)粗略想法,请在此处查看我的答案..

For an rough idea (on how to construct/use the expando object), see my answer here.

这篇关于基于ASP.NET Core自定义策略的授权-不清楚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆