【问题标题】:Pass parameters to a Requirement/Policy in ASP.NET MVC 6将参数传递给 ASP.NET MVC 6 中的需求/策略
【发布时间】:2015-08-24 11:39:11
【问题描述】:

我试图在 ASP.NET vNext 中创建一个自定义授权属性,直到我在这篇文章中从@blowdart 找到了这个出色的答案:

https://stackoverflow.com/a/31465227/1756978

表明授权要求现在是要走的路。答案非常明确,但没有说明如何将参数传递给此要求/策略。

我正在尝试做的是移植具有此签名的 MVC 5 自定义授权属性:

[Autorizacion(Requires = enumPermission.DeleteCustomer)]

因为我使用了一组非常自定义的权限,这些权限在后端/前端镜像为枚举/字符串。

由于尚未记录此功能,我感到有些失落……有人可以提供指导吗?

提前致谢

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc


    【解决方案1】:

    我碰巧想出了一个可以满足我要求的解决方法,希望它对你也有帮助。

    就我而言,我需要将IHttpContextAccessor 和EFCore 的AppDbContext 传递给我的Requirement 类。

    在我的Startup.cs 中,我这样写:

    services.AddAuthorization(options =>
    {
        options.AddPolicy("ThePolicy", policy => policy.Requirements.Add( new ThePolicyRequirement() ));
    });
    services.AddScoped<IAuthorizationHandler, ThePolicyAuthorizationHandler>();
    

    ThePolicyAuthorizationHandler 类:

    public class ThePolicyAuthorizationHandler : AuthorizationHandler<ThePolicyRequirement>
    {
        readonly AppDbContext _appContext;
        readonly IHttpContextAccessor _contextAccessor;
    
        public ThePolicyAuthorizationHandler(AppDbContext c, IHttpContextAccessor ca)
        {
            _appContext = c;
            _contextAccessor = ca;
        }
    
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ThePolicyRequirement requirement)
        {
            var result = await requirement.isPass(_appContext, _contextAccessor, context);
            if (result)
                context.Succeed(requirement);
            else
                context.Fail(requirement);
        }
    }
    

    ThePolicyRequirement 类:

    public class ThePolicyRequirement : IAuthorizationRequirement
    {
        AppDbContext _context;
        IHttpContextAccessor _contextAccessor;
        AuthorizationHandlerContext _authHandlerContext;
    
        public async Task<bool> isPass(AppDbContext context, IHttpContextAccessor contextAccessor, AuthorizationHandlerContext authorizationHandlerContext)
        {
            _context = context;
            _contextAccessor = contextAccessor;
            _authHandlerContext = authorizationHandlerContext;
    
            //logic here
    
            return result;
        }
    }
    

    关键思想是使用ThePolicyAuthorizationHandler尽可能的获取所有需要的对象,并传递给ThePolicyRequirement做授权机制的逻辑。

    【讨论】:

      【解决方案2】:

      确实,@blowdart 的帖子很有见地,据我了解,要理解的关键如下:

      对身份的授权行为。身份由以下人员创建 身份验证。

      因此,身份似乎是由身份验证过程创建的。

      然后(如果您愿意)您可以启动授权流程。这意味着创建一个自定义 authorization requirements,此要求将查看这些身份并对其采取行动。

      简单地说,这就是我认为正在发生的事情:

      1. 正如吹镖的帖子中提到的,我们应该有一些 恰好执行实际操作的身份验证中间件 验证。成功通过身份验证后,您可以采取任何措施 您想从该已验证用户那里获得的信息并创建一个 认证ClaimsPrincipal

        例如,我们可以在ClaimsPrincipal 中存储 用户拥有的权限。

      2. 然后,当您创建 authorization requirement 时,您会查看 ClaimsPrincipal,从 ClaimsPrincipal 并根据任何情况采取适当的行动 您想要的业务规则。

        假设您无法将权限集存储到 ClaimsPrincipal 出于某种原因,可以轻松存储 UserId 并从要求中,从 ClaimsPrincipal,调用数据库并获取权限集 然后对它们采取行动。

      结论:

      因此,简而言之,我认为您不会向需求传递东西,我认为您可以从ClaimsPrincipal获取它们。

      在您的示例中,您可以创建一个读取 ClaimsPrincipal 的需求,并将任何值与您的 Enum 进行比较并采取行动。

      让我们知道您成功完成了什么以及它是否有效。

      如果我对此的理解是错误的,那么请随时纠正我,因为所有这些都是新东西:-)

      【讨论】:

      • 是的,我正在将内容传递给需求...该声明包含标记在一个位数组中的所有用户权限,该位数组编码在一个 base64 字符串中。对此,我需要检查是否授予了具体权限以过滤给定 api 操作中的授权,这就是为什么我需要传递从映射到前一个数组的枚举中选择的具体权限的原因。这样我就可以在不读取数据库的情况下超快速地检查权限,而且我对它们有智能感知,因为它们是枚举的一部分。这是目前在 MVC 5 中实现的,就像一个魅力。
      • @Vi100 我目前正在开发一个 ASP.NET MVC 5 项目,我想通过数据库表将用户角色动态分配给控制器。我是否正确理解您已经在 ASP.NET MVC 5 应用程序中实现了此功能?如果是,你愿意分享吗?如果没有,您能否指出您用于开发解决方案的相关文档?非常感谢任何考虑/帮助!
      猜你喜欢
      • 2020-01-21
      • 1970-01-01
      • 2010-09-14
      • 2011-02-04
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多