好的,ASP.NET Core中基于自定义策略的授权。我有点理解这个新的身份框架的想法,但仍然没有100%清楚你可以用这个来实现。假设我们在HomeController中有一个名为List的Action。此操作将查询并显示数据库中的产品列表。必须访问此列表的用户必须是Marketing部门的一部分。因此,在我们的政策中,我们检查用户是否有一个名为Division的声明,其值是Marketing。如果是,那么他将被允许查看列表,否则不会。我们可以像这样装饰我们的行动:
[Authorize(Policy = "ProductsAccess")]
public IActionResult List()
{
//do query and return the products view model
return View();
}
这一切都很好。它会完美地运作。
场景1:如果我想在产品级别添加策略,并且根据策略,用户将只看到其部门的产品,该怎么办?所以营销人员会看到他的产品,R& D会看到他的等等。我怎样才能做到这一点?是否可以通过政策完成?如果是的话怎么样?
场景2:现场级别的访问权限如何?让我们说也许我想隐藏某些字段?示例:所有产品都有某些必须对Managers可见且对其他用户隐藏的列?可以使用自定义策略完成吗?如果是的话怎么样?
答案 0 :(得分:4)
对于场景1 ,您可以使用resource based authorization。
本质上,您将IAuthorizationService
注入您的服务或控制器,然后拥有一个或多个派生形式为AuthorizationHandler<TRequirement, TDocument>
的授权处理程序,然后调用
if(await _authorizationService.AuthorizeAsync(User, document, "MyPolicy"))
{
// Success, user has access to it
}
下行:您必须从数据库中获取所有产品,然后在内存中进行过滤,因此它适用于单个文档或较小的数据,您不需要分页。即使在较小的数据上,分页也会破坏它(即如果您要求50个产品,但是用户无法访问其中的40个产品,则只返回10个,尽管页面大小为50)。
使用EF Core 2.0可以实现替代方案(如果您使用EF Core作为您的ORM)。您可以添加全局过滤器,这些过滤器将应用于对特定实体的所有查询。
有关详细信息,请参阅Entity Framework Core 2.0 Announcement博文:
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 );
}
}
它可能适用于您的情况,也可能不适用,这取决于您是否有可以使用的行级数据(即某种“资源所有者”字段)。
根据我所知,场景2 不可能开箱即用,你必须自己实现一些东西,但这是一个非常复杂的话题(如果你曾经工作过的话)使用Dynamics CRM,你知道我的意思。)
<强>更新强>
只是为了快速实现,您可以尝试将响应包装在ExpandoObject
(这是使用dynamic
关键字时使用的基础)并迭代它,删除用户没有的属性在从控制器操作返回之前有权访问或编写授权过滤器,这将自动为特定或所有控制器执行此操作。
对于一个粗略的想法(关于如何构造/使用expando对象),请参阅我的回答here。
答案 1 :(得分:3)
我不认为政策旨在解决您的案件。我不确定它是否可能,即使它可能,我觉得代码本身会受到它带来的复杂性和混乱的影响。我不会给我的授权过滤器那么大的责任。
至于您的第二种情况,您可以根据角色,声明或当前用户的任何内容,跳过在视图中输出某些数据。使用策略解决问题似乎不必要地复杂。
使用策略来制作它,授权是否允许用户甚至运行方法。与归还的内容有何不同?在正常的代码流程中处理它。