来自数据库表的ASP.NET Core 2授权

时间:2018-12-13 03:53:06

标签: c# asp.net-core authorization asp.net-core-2.0

我有一系列网页,对这些页面的授权是在自定义数据库表中定义的。例如,我有一个名为“超级用户”的角色,并且允许该角色在某些网页上访问。我已将用户分配给该角色。

我不明白如何将Authorize属性放在控制器上并传递页面名称(视图),然后从数据库中读取某种类型的自定义处理程序,以查看用户是否在组中获得许可。我一直在这里阅读基于策略的授权:https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2,并试图根据自己的情况来理解它。

我是否具有基于策略的授权,或者在允许用户访问页面之前是否有另一种方法可以对数据库进行权限检查?

3 个答案:

答案 0 :(得分:3)

Authorize属性本身仅用于指定特定页面或控制器上所需的授权类型。该属性将用于身份框架之外,并且可以包括角色,策略和身份验证方案。

您需要在Identity框架和数据库之间建立一座桥梁,这可以通过自定义UserStoreRoleStore来完成,这在this page中有详细描述。 / p>

总结一个非常复杂的过程:

  1. Authorize属性指示浏览器对您的用户进行身份验证
  2. 您的用户被重定向到身份验证页面
  3. 如果成功,将为您提供一个ClaimsPrincipal实例,然后您需要通过自定义UserStore来映射到数据库用户
  4. 然后可以根据数据库角色检查您的用户

这是所有这些操作的简短示例(由于代码太多,因此无法完全完成)。

Startup.cs

// This class is what allows you to use [Authorize(Roles="Role")] and check the roles with the custom logic implemented in the user store (by default, roles are checked against the ClaimsPrincipal roles claims)
public class CustomRoleChecker : AuthorizationHandler<RolesAuthorizationRequirement>
{
    private readonly UserManager<User> _userManager;

    public CustomRoleChecker(UserManager<User> userManager)
    {
        _userManager = userManager;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)
    {
        var user = await _userManager.GetUserAsync(context.User);

        // for simplicity, I use only one role at a time in the attribute
        var singleRole = requirement.AllowedRoles.Single();
        if (await _userManager.IsInRoleAsync(user, singleRole))
            context.Succeed(requirement);
    }
}

public void ConfigureServices(IServiceCollection services)
{
    services
    .AddIdentity<User, Role>()
    .AddUserStore<MyUserStore>()
    .AddRoleStore<MyRoleStore>();

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

其中UserRole是您的EF Core实体。

MyUserStore

public class MyUserStore : IUserStore<User>, IUserRoleStore<User>, IQueryableUserStore<User>
{
    private Context _db;
    private RoleManager<Role> _roleManager;
   ...

    public async Task<User> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
    {
        // bridge your ClaimsPrincipal to your DB users
        var user = db.Users.SingleOrDefault(_ => _.Email.ToUpper() == normalizedUserName);
        return await Task.FromResult(user);
    }

   ...
    public async Task<bool> IsInRoleAsync(User user, string roleName, CancellationToken cancellationToken)
    {
        if (roleName == null)
            return true;

        // your custom logic to check role in DB
        var result = user.Roles.Any(_ => _.RoleName == roleName);
        return await Task.FromResult(result);
    }

答案 1 :(得分:0)

如果您正在寻找基于角色的身份验证,这似乎是一个很好的资源:https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.2

您可以向类添加属性,其中的任何内容都需要您指定的角色:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlPanelController : Controller
{
    public ActionResult SetTime()
    {
    }

    [Authorize(Roles = "Administrator")]
    public ActionResult ShutDown()
    {
    }
}

答案 2 :(得分:0)

.Net Core->如果要使用基于策略的方法,则必须在startup.cs的ConfigureServices方法中定义策略定义

示例:

 services.AddAuthorization(options =>
            {
                options.AddPolicy("UserPolicy", policy => policy.RequireRole("USER"));
            });

然后您可以在控制器或操作方法中应用以下策略。

授权(策略=“ UserPolicy”)