【问题标题】:How to reload a Custom Attribute during run-time? ASP.NET Core MVC如何在运行时重新加载自定义属性? ASP.NET 核心 MVC
【发布时间】:2019-09-16 02:09:00
【问题描述】:

我有一个应用程序,用户可以在其中创建新角色。 某些操作只能由某些角色访问。为了检查是否允许用户执行某个操作,我使用了自定义 AuthorizeAttribute,类似于https://stackoverflow.com/a/40300184

[AuthorizeRoles(Permission.Unlink, Permission.Link)] 
[HttpGet("link")]
    public IActionResult Link(int id)
    {
        ...
    }

AuthorizeRolesAttribute 类:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params Permission[] permissions)
    {   
        Roles = GetRoles(permissions);
    }
}

获取角色:

public static string GetRoles(params Permission[] permissions)
{
    DataRowCollection rows = DatabaseHelper.RoleTable.Rows;
    List<string> allowedRoles = new List<string>();
    foreach (DataRow row in rows)
    {
        bool allowed = true;
        foreach (Permission permission in permissions)
        {
            if ((bool)row[permission.ToString()] == false)
                allowed = false;
        }
        //if all required permissions are true in this role it is added to the allowed roles
        if (allowed)
            allowedRoles.Add(row["ROLE"].ToString());
    }
    return string.Join(",", allowedRoles);
}

当应用程序启动时,每个具有 AuthorizeRolesAttribute 的方法都会调用 GetRoles 方法来确定允许哪些角色使用该方法。但是,当添加新角色时,这适用于现有角色。该属性不会重新评估角色。我需要更新属性并允许新角色使用该方法,而无需重新启动应用程序。

我尝试在添加新角色后运行以下代码。 (由https://stackoverflow.com/a/12196932建议)

typeof(UsersController).GetMethod(nameof(UsersController.Link)).GetCustomAttributes(false);

这确实会导致 AuthorizeRolesAttribute 再次调用 GetRoles(),并且会返回一个包含新角色的字符串。但是,当尝试以具有新角色的用户身份访问“链接”方法时,我得到了 403 Forbidden 状态。

【问题讨论】:

  • 那么问题出在验证角色的代码上。
  • 已经存在的角色虽然被正确验证。此外,在重新启动应用程序后,新角色将被正确验证。所以在我看来 GetRoles() 方法工作正常。但是,由于某种原因,AuthorizeRoles 属性没有相应地起作用。

标签: c# .net asp.net-core-mvc authorization asp.net-core-2.1


【解决方案1】:

我找到了解决方案。而不是这个:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params Permission[] permissions)
    {   
        Roles = GetRoles(permissions);
    }
}

我现在有了这个:

public class AuthorizeRolesAttribute : Attribute, IAuthorizationFilter 
{
    private readonly Permission[] permissions;
    public AuthorizeRolesAttribute(params Permission[] permissions)
    {
        this.permissions = permissions;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        string[] roles = Authentication.GetRoles(permissions).Split(",");
        bool allowed = context.HttpContext.User.Claims.Any(c => c.Type.Contains("role") && roles.Contains(c.Value));
        if (!allowed)
            context.Result = new ForbidResult();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多