【问题标题】:Set authorize attribute for Custom policy for all controller and Actions at global为全局的所有控制器和操作设置自定义策略的授权属性
【发布时间】:2017-03-04 08:20:39
【问题描述】:

我是 .Net / ASP.NET 开发的新手,我正在尝试使用我想在全局级别添加的自定义策略,这样我就不必在每个控制器中添加 [Authorize] 属性对于我制定的政策。

我创建了一个名为 SuperAdminUsers 的策略并使用来自 UserNamesRequirement 的自定义要求,我想将其设置在全局级别,这样所有 SuperAdminUsers 都可以访问所有控制器和操作。

以下是我在startup.cs 文件中创建的策略。

services.AddAuthorization(
        option =>
        {
            option.AddPolicy("Admin", policy => policy.RequireRole("DOMAIN\\GroupName"));
            option.AddPolicy("SuperAdminUsers", policy => policy.Requirements.Add(new UserNamesRequirement("DOMAIN\\USER1", "DOMAIN\\USER2"))
        }
);
// Add Custom filters
services.AddMvc(
    config =>
    {
        var policy = new AuthorizationPolicyBuilder();
        policy.Requirements.Add(new UserNamesRequirement("DOMAIN\\USER1"));
                policy.Build();
                config.Filters.Add(new AuthorizeFilter(policy));
    }
);

在上面的config.Filters 中,我收到如下截图所示的错误:

这是我的客户需求和处理类:

public class UserNamesRequirement : IAuthorizationRequirement
{
    public UserNamesRequirement(params string[] UserNames)
    {
        Users = UserNames;
    }
    public string[] Users { get; set; }
}

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserNamesRequirement requirement)
{
        // var userName = context.User.FindFirst(ClaimTypes.NameIdentifier).Value;
        var userName = context.User.Identity.Name;

        if (requirement.Users.ToList().Contains(userName))
            context.Succeed(requirement);
        return Task.FromResult(0);
}

更新 1:

使用以下代码更新启动文件,但仍然无法授权。

services.AddMvc
        (
            config =>
            {
                var policyBuilder = new AuthorizationPolicyBuilder();
                policyBuilder.Requirements.Add(new UserNamesRequirement("DOMAIN\\USER1", "DOMAIN\\USER2"));
                var policy = policyBuilder.Build();
                config.Filters.Add(new AuthorizeFilter(policy));
            }
        );

我正在尝试访问的控制器:

[Authorize(Policy = "Admins")]
[Authorize(Policy = "SuperAdminUsers")]
public class OperatingSystemsController : Controller
{
    private readonly ServerMatrixDbContext _context;

    public OperatingSystemsController(ServerMatrixDbContext context)
    {
        _context = context;    
    }

    // GET: OperatingSystems
    public async Task<IActionResult> Index()
    {
        return View(await _context.OperatingSystems.ToListAsync());
    }
}

这是我在 str 输出日志文件中看到的内容:

注意:我删除了真实域和用户名。

Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost/demo/OperatingSystems/Create  
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful for user: DOMAIN\USER1.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: DOMAIN\USER1.
warn: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]

非常感谢任何帮助。

【问题讨论】:

  • 为所有控制器创建一个基类,并仅为该类设置 [Authorize]。
  • 所以,我创建了一个基类并添加了 Authorize,然后我将它引入到所有控制器中,就像这样 Public class SearchController : Controller, BaseAuth { } ?
  • 我的意思是这个 BaseController : Controller, YourController: BaseController

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


【解决方案1】:

过滤器是为所有控制器和操作设置授权属性的一种方法。例如,这里有一个需要特定用户名的策略。

services.AddMvc(config =>
{
    var policy = new AuthorizationPolicyBuilder()
                     .RequireUserName("DOMAIN\\USERID")
                     .Build();

    config.Filters.Add(new AuthorizeFilter(policy));
});

您收到错误是因为AuthorizationFilter 构造函数需要policy 而不是policyBuilder。为了更清楚起见,这是更改了变量名称的代码。

services.AddMvc(config =>
{
    var policyBuilder = new AuthorizationPolicyBuilder();
    policyBuilder.Requirements.Add(new UserNamesRequirement("DOMAIN\\USER1"));

    // this will NOT work
    policyBuilder.Build();
    config.Filters.Add(new AuthorizeFilter(policyBuilder));

    // this will work
    var policy = policyBuilder.Build();
    config.Filters.Add(new AuthorizeFilter(policy));

});

【讨论】:

  • 谢谢肖恩。这有很大帮助,但是如何实现我用来利用自定义 handlerrequirement 类的自定义策略?我在问题中添加了更多详细信息,但出现错误。
  • @ray Build() 方法返回一个policy。它不会将policyBuilder 更改为policy。我的编辑可能会为您澄清这一点。
  • 啊..现在说得通了。 :) 感谢您花时间向我解释。非常感谢您的帮助。
  • hmm.. 看起来过滤不起作用。我正在尝试访问的控制器之一获得 403 页。
  • 这可能是operatingsystemsController 控制器的顶级[Authorize] 属性吗?我从另一个控制器中删除了所有[Authorize],它正在工作。
猜你喜欢
  • 2016-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多