如何从数据库获取用户角色以填充AuthorizeAttribute

时间:2019-05-20 15:39:51

标签: c# asp.net-core authorization microservices roles

我有一个.netcore mvc应用程序,在其中我在CustomRoles类中具有角色:

public class CustomRoles
    {
       ///<Summary>Manager role</Summary>
       public const string Manager = "Manager";

       ///<Summary>Publisher role </Summary>
       public const string Publisher = "Publisher";
    }

在我的控制器中,我在端点上设置了Authorize:

    /// <summary>
    /// ASYNC Version: Get a List of Journals based on a Week Id
    /// </summary>
    /// <param name="weekId">Database unique Week ID</param>       
    /// <response code="204">No Content</response>
    /// <response code="400">Bad Request</response> 
    /// <returns></returns>
    [Authorize(Roles = CustomRoles.Manager +","+ CustomRoles.Publisher)]
    [HttpGet("GetPartnerJounalsByIdAsync/")]
    [ProducesResponseType(200, Type = typeof(JounalsPartnerGetResponse))]
    [ProducesResponseType(204)]
    [ProducesResponseType(400)]
    public async Task<ActionResult> GetPartnerJournalsByIdAsync([Required]int weekId)
    {
        //get from db
    }

我想从数据库中填充角色,而不是在类中对其进行硬编码,因此我可以实现:

[Authorize (Roles = //Roles from the database)]

这是我创建的解决方案,但我遇到了麻烦。我实现了一个Role类:

 public class Role
    {
        /////<Summary>Manager role</Summary>
        public string RoleName { get; set; }
    }

以及从数据库获取角色的方法:

    /// <summary>
    /// Get All Roles
    /// </summary>
    /// <returns></returns>
    public async Task<List<Role>> GetRoles()
    {
        GetResponse response = new GetResponse();
        List<Role> CRoles = new List<CustomRoles>();
        response = await database.ObjectGetTypedListAsync<Role>("", "Role");
        CRoles = (List<Role>)response.StronglyTypedObject;
        return CRoles;
    }

有什么想法可以实现这一目标吗?

2 个答案:

答案 0 :(得分:1)

要基于数据库中的数据检查角色,可以像

那样实现自己的IAuthorizationFilter
[AttributeUsage(AttributeTargets.Class)]
public class MyAuthorize : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
        var roles = dbContext.Roles.ToList();
        foreach (var role in roles)
        {
            if (!context.HttpContext.User.IsInRole(role.Name))
            {
                context.Result = new ForbidResult();
            }
        }
    }
}

并像这样使用它:

[MyAuthorize]
public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";

    return View();
}

答案 1 :(得分:0)

我曾经使用过类似爱德华的回答。现在,我只使用 AccountController 中的 Login 方法:

public class AppUser
{
    public string DisplayName { get; set; }
    [Required]
    public string Username { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

[HttpPost, ValidateAntiForgeryToken]
[AllowAnonymous]
public async Task<IActionResult> Login(string returnUrl, AppUser model)
{
    // if input parameters are valid…
    if (ModelState.IsValid)
    {
        // attempt to authenticate
        var user = _authService.Login(model.Username, model.Password);
        if (user != null)
        {
            // if login was successful, create Claims for Username and DisplayName
            var userClaims = new List<Claim>
            {
                new Claim("displayName", user.DisplayName),
                new Claim(ClaimTypes.Name, user.Username)
            };
            // as well as all the permitted Roles
            var permissions = (from p in _context.Permissions
                            where p.Username == user.Username
                            select p.Name);
            foreach (var role in permissions){
                userClaims.Add(new Claim(ClaimTypes.Role, role));
            }

            ClaimsIdentity identity = new ClaimsIdentity(userClaims, _authService.GetType().Name);
            identity.Label = user.DisplayName;
            // save the ClaimsIdentity in the authentication cookie
            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(identity),
                // the cookie will persist for 7 days
                new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTimeOffset.UtcNow.AddDays(7)
                }
            );
        }
    }
    return View(model);
}

显然,您有自己的身份验证。 AppUser 是登录视图中使用的模型。 Cookie 身份验证是免费的 :-)

现在您的控制器只需在您的控制器方法上使用 [Authorize(Roles = "permission")],其中 permission 是上面查询中的 p.name