ASP.NET Core Custom Policy Based Authorization - unclear

拜拜、爱过 提交于 2019-12-04 08:01:56

For Scenario 1 you can use resource based authorization.

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
}

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).

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.

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).

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).

Update

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.

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

I don't think policies were designed to solve the cases you have. I'm uncertain if it's possible, and even if it would, I feel like the code itself would suffer from the complexity and confusion it would bring. I wouldn't give my authorization filters that much responsibility.

As for your second scenario, you could just skip outputting certain data in your view based on the role, claim or whatever of the current user. Seems unnecessarily complex to solve that with policies.

Use policies for what it was made for, authorizing if the user is allowed to even run a method. Any differences to what is being returned? Handle it in the normal code flow.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!