使用Windows身份验证创建基于角色的授权

时间:2020-02-07 00:41:35

标签: asp.net-core

我有一个ASP.NET Core应用程序,我想在其中添加基于角色的身份验证。我正在使用Windows身份验证,因为它是一个Intranet应用程序。我已经有一个自定义数据库,其中包含坦率地说未映射到IdentityFramework中字段的用户/角色。我可以通过Context.User.Identity.Name轻松获取登录用户的名称。然后,我想在自定义用户/角色表中查找该用户,以获取该用户的可用角色。然后,我想使用在Controller或Action方法级别装饰的基于注释的身份验证筛选器。例如,[Authorize(roles =“ admin”)]。

我能够通过关闭Windows身份验证并使用带有Cookie的表单身份验证来使其正常工作。在AccountController中,我运行了如下代码:

List

然后我将声明存储在cookie中。然后,当我使用[Authorize(roles =“ admin”)]装饰Controller时,便可以毫无问题地检索视图。授权有效。我想在不登录用户的情况下为WindowsAuthentication复制相同的功能。我尝试使用ClaimsTransformer并实现有效的基于策略的授权。但是,如果我用[Authorize(roles =“ admin”)]装饰它,当我导航到操作方法时它会炸弹。这是ClaimsTransformer:

          using(LDAPConnection connection = new LDAPConnection(loginModel.UserName,loginModel.Password))
            {
                List<Claim> claims = new List<Claim> {
                    new Claim(ClaimTypes.Name, loginModel.UserName),
                    new Claim(ClaimTypes.Role, "admin")
                };
                ClaimsIdentity userIdentity = new ClaimsIdentity(claims,"login");
                ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
                await HttpContext.SignInAsync(
                    CookieAuthenticationDefaults.AuthenticationScheme,
                    new ClaimsPrincipal(principal),
                    new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTime.Now.AddDays(200)
                    });
                return Redirect("/");
            }

为了使用[Authorize(Roles =“ admin”)],我缺少了哪一部分?顺便说一句,我目前正在使用ASP.NET Core 2.2。

2 个答案:

答案 0 :(得分:1)

您可以编写自定义策略授权处理程序,在其中获得所有用户角色,并检查它们是否包含所需的角色名称。

请参阅以下步骤:

1。创建CheckUserRoleRequirement(接受参数)

public class CheckUserRoleRequirement: IAuthorizationRequirement
{
    public string RoleName { get; private set; }

    public CheckUserRoleRequirement(string roleName)
    {
        RoleName = roleName;
    }
}

2。创建CheckUserRoleHandler

public class CheckUserRoleHandler : AuthorizationHandler<CheckUserRoleRequirement>
{
    private readonly IServiceProvider _serviceProvider;

    public CheckUserRoleHandler(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   CheckUserRoleRequirement requirement)
    {
        var name = context.User.Identity.Name;
        using (var scope = _serviceProvider.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<YourDbContext>();

           //your logic to look up the user in the custom user/roles table in order to get the available roles for that user
            List<string> roles = dbContext.UserRoles.Where(...;
            if (roles != null && roles.Contains(requirement.RoleName))
            {
                context.Succeed(requirement);
            }
        }
        return Task.CompletedTask;
    }
}

3.ConfigureServices中的注册处理程序

services.AddAuthorization(options =>
{
    options.AddPolicy("AdminRole", policy =>
        policy.Requirements.Add(new CheckUserRoleRequirement("Admin")));
});

services.AddSingleton<IAuthorizationHandler, CheckUserRoleHandler>();

4。用法

[Authorize(Policy = "AdminRole")]

答案 1 :(得分:1)

我知道这有点晚了,但我今天一直在解决同一问题,我在类似帖子中看到的答案都没有解决我的问题。

以下是我通过 Windows 身份验证在控制器上使用 [Authorize(Roles = "Admin")] 所采取的步骤。

  1. 在 Startup.cs 的 UseAuthentication() 方法中仔细检查 UseAuthorization() 是否位于 Configure() 之前
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthentication(); // <--- this needs to be before
            app.UseAuthorization(); // <----this

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Hccc}/{action=Index}/");
            });
        }
  1. 有一个声明转换器来处理必要的角色。例如,
        public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
        {
            var ci = (ClaimsIdentity)principal.Identity;
            var user = UserAuth.GetUserRole(ci.Name); // gets my user from db with role
            // handle your roles however you need.
            foreach(var role in user.Roles)
            {
                var roleClaim = new Claim(ci.RoleClaimType, role.RoleName);
                ci.AddClaim(roleClaim);
            }

            return Task.FromResult(principal);
        }
  1. 在 Startup.cs 中设置 ConfigureServices() 方法来处理授权
        services.AddSingleton<IClaimsTransformation, ClaimsTransformer>();
        // Implement a policy called "AdminOnly" that uses "Windows" authentication
        // The policy requires Role "Admin"
        services.AddAuthorization(options =>
        {
            options.AddPolicy("AdminOnly", policy =>
            {
                policy.AddAuthenticationSchemes("Windows");
                policy.RequireRole("Admin");
            });
        });
        services.AddMvc();
        services.AddControllersWithViews();
  1. 使用 [Authorize] 标签实施政策。就我而言,我想阻止对控制器的访问,除非用户是“管理员”。
        [Authorize(Policy = "AdminOnly")]
        public class UsersController : Controller
        {

        }