.NET Core Identity API 具有基于权限的身份验证

.NET Core Identity API with permission based auth

我是 Identity API 的新手,但在我的 Web 应用程序中:机构用户为自己的机构创建其他用户,他们想决定谁可以看到此页面或 not.My 这样的控制器方法;

    [Authorize]
    public IActionResult Privacy()
    {
        return View();
    }

但用户也有权执行此枚举之类的任何操作,并且枚举大于 50;

    public enum PermissionTypes
    {
        UserCreate = 1,
        UserEdit = 2,
        UserDelete = 3,
        ....
    }

我做了一些研究,发现了基于策略的授权,但是当你创建一个新策略时,你必须在 Startup.cs 声明,这对我不利,因为当你这样做时,你总是在 production.What 我需要的是类似的东西 ;

    [CustomAuth(PermissionTypes.UserCreate)]
    public IActionResult Privacy()
    {
        return View();
    }

这种情况有什么解决办法吗?

您需要在操作中使用角色。

ASP .NET Core Identity Roles

有很多方法可以做到这一点。很多人推荐基于声明和策略的安全...我个人觉得这种方法有点"stiff".

所以我做的有点不同:

首先像这样创建一个class:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Identity;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Bamboo.Web.CoreWebsite.Membership
{
  public class PermissionHandler : AuthorizationHandler<RolesAuthorizationRequirement>
  {
    private readonly IUserStore<CustomUser> _userStore;        

    public PermissionHandler(IUserStore<CustomeUser> userStore)
    {
      _userStore = userStore;         
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)
    {
      if(context == null || context.User == null)
        return;

      var userId = context.User.FindFirst(c => string.CompareOrdinal(c.Type, ClaimTypes.NameIdentifier) == 0);//according to msdn this method returns null if not found

      if(userId == null)
        return;

      // for simplicity, I use only one role at a time in the attribute
      //but you can use multiple values
      var permissions = requirement.AllowedRoles.ToList();

      var hasPermissions = //here is your logic to check the database for the actual permissions for this user.
                           // hasPermissions is just a boolean which is the result of your logic....

      if(hasPermissions)
        context.Succeed(requirement);//the user met your custom criteria
      else
        context.Fail();//the user lacks permissions.
    }
  }
}

现在像这样在 startup.cs 文件中注入 PermissionHandler:

    public void ConfigureServices(IServiceCollection services)
    {
          // Custom Identity Services
          ........

          // custom role checks, to check the roles in DB 
          services.AddScoped<IAuthorizationHandler, PermissionHandler>();

//the rest of your injection logic omitted for brevity.......
    }

现在像这样在您的操作中使用它:

[Authorize(Roles = PermissionTypes.UserCreate)]
public IActionResult Privacy()
{
   return View();
}

请注意,我没有创建自定义属性...正如我所说,有很多方法可以做到这一点。 我更喜欢这种方式,因为代码更少,没有硬编码的政策或声明或任何其他复杂性,您可以使其 100% 由数据驱动。

这是一个复杂的主题,因此可能需要进行额外的调整才能发挥作用。

我还使用 ASP.NET Core 2.2,它可能与 3.0 不同。

但它应该为您提供一种基于许可的授权方式。