授权多个角色

时间:2019-11-05 06:31:46

标签: authentication asp.net-core authorization claims-based-identity

该应用程序是在asp.net core 3上开发的。当用户担任多个角色时,面临授权问题。

用户角色

public enum UserRole
{
   None = 0x0,
   View = 0x1,
   ConfirmAlarm = 0x2,
   ObjectScaling = 0x4,
   SchemeEditor = 0x8,
   ObjectEditor = 0x10
}

索赔

private async Task Authenticate(User user)
{
   var claims = new List<Claim>
   {
      new Claim(ClaimsIdentity.DefaultNameClaimType, user.Login),
      new Claim(ClaimsIdentity.DefaultRoleClaimType, ((UserRole)user.Role).ToString()),
      new Claim("uGroupId", user.GroupId.ToString()),
      new Claim("uInfo", user.Info),
      new Claim("uTheme", user.Theme)
   };
   ClaimsIdentity id = new ClaimsIdentity(claims, "ApplicationCookie", 
   ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
   await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new 
   ClaimsPrincipal(id));
}

控制器方法:

[Authorize(Roles = "View")]
[HttpPost("[action]")]
public async Task<string> SomeAction()
{
   //...some code
}

如果用户具有“查看,ConfirmAlarm,ObjectScaling,SchemeEditor,ObjectEditor”的所有角色,则无法在控制器中对该用户授权该方法。

可能是什么问题?是否需要创建自定义AuthorizeAttribute?

更新

添加了两个类: RolesRequirement.cs

public class RolesRequirement : IAuthorizationRequirement
{
    public string RoleName { get; }

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

RoleHandler.cs

public class RoleHandler : AuthorizationHandler<RolesRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesRequirement requirement)
    {
        string roles = context.User.Claims.FirstOrDefault(x => x.Type == ClaimsIdentity.DefaultRoleClaimType).Value;
        if (!string.IsNullOrEmpty(roles))
        {
            if (roles.Contains(requirement.RoleName))
            {
                context.Succeed(requirement);
            }
        }

        return Task.CompletedTask;
    }
}

将策略添加到startup.cs

services.AddAuthorization(options =>
{
    options.AddPolicy("View", policy => policy.Requirements.Add(new RolesRequirement("View")));
    options.AddPolicy("ConfirmAlarm", policy => policy.Requirements.Add(new RolesRequirement("ConfirmAlarm")));
    options.AddPolicy("ObjectEditor", policy => policy.Requirements.Add(new RolesRequirement("ObjectEditor")));
});

并在控制器方法之前添加属性。

[Authorize(Policy = "View")]
[Authorize(Policy = "ObjectEditor")]
[HttpPost("[action]")]
public async Task<string> SomeAction()
{
   //...some code
}

1 个答案:

答案 0 :(得分:1)

请尝试以下行:

ClaimsIdentity id = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme,
            ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);

代替:

ClaimsIdentity id = new ClaimsIdentity(claims, "ApplicationCookie", 
            ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);

CookieAuthenticationDefaults.AuthenticationSchemeCookies,它与Startup.cs中cookie的默认authenticationScheme匹配:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie();

已更新:

您可以手动检查索赔:

services.AddAuthorization(options =>
{
    options.AddPolicy("AllowedView", policy =>
    {
        policy.RequireAssertion(context =>
        {

            var roles = context.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role)?.Value;

            var  listRolesElements = roles.Split(',').ToList();


            return listRolesElements.Contains("View");
        });
    });
});

并在需要View权限的控制器上应用策略:

[Authorize(Policy = "AllowedView")]