角色/用户的ASP.NET MVC黑名单

时间:2015-06-19 16:45:38

标签: c# asp.net asp.net-identity authorize-attribute blacklist

问题摘要:在ASP.NET MVC中,是否有一种干净的方法可以阻止特定用户或角色访问某个操作?

显然,以下内容允许角色AdminEditor访问整个控制器。

[Authorize(Roles = "Admin, Editor")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

如果我只希望Admin角色可以访问About操作,我可以执行以下操作:

[Authorize(Roles = "Admin, Editor")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [Authorize(Roles = "Admin")] // this will take precedence over the controller's authorization
    public ActionResult About()
    {
        return View();
    }
}

有没有办法在不列出需要访问权限的每个角色的情况下完成此操作,并且只指定应该阻止访问的角色?

2 个答案:

答案 0 :(得分:1)

以下是我用来解决此问题的类的代码。它源自public override async Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser) { var userIdentity = await CreateUserIdentityAsync(user); // your code here userIdentity.AddClaim(new Claim(ClaimTypes.Gender, "male")); // AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie); if (rememberBrowser) { var rememberBrowserIdentpublic override async Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser) { var userIdentity = await CreateUserIdentityAsync(user); // your code here userIdentity.AddClaim(new Claim(ClaimTypes.Gender, "male")); // uthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie); if (rememberBrowser) { var rememberBrowserIdentity = AuthenticationManager.CreateTwoFactorRememberBrowserIdentity(ConvertIdToString(user.Id)); AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity, rememberBrowserIdentity); } else { AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity); } } ,并且允许任何经过身份验证的用户通过匹配参数设置的规范。

(请注意,重要的方法是AuthorizeAttribute - 其他所有内容基本上都是从AuthorizeCore复制或继承的)

AuthorizeAttribute

您可以在控制器或其他[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class BlackListAttribute : AuthorizeAttribute { private static readonly string[] _emptyArray = new string[0]; private string _roles; private string _users; private string[] _rolesSplit = _emptyArray; private string[] _usersSplit = _emptyArray; public new string Roles { get { return _roles ?? String.Empty; } set { _roles = value; _rolesSplit = SplitString(value); } } public new string Users { get { return _users ?? String.Empty; } set { _users = value; _usersSplit = SplitString(value); } } // This is the important part. Everything else is either inherited from AuthorizeAttribute or, in the case of private or internal members, copied from AuthorizeAttribute. protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } IPrincipal user = httpContext.User; if (user == null || user.Identity == null || !user.Identity.IsAuthenticated) { return false; } if (_usersSplit.Length > 0 && _usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) { return false; } if (_rolesSplit.Length > 0 && _rolesSplit.Any(user.IsInRole)) { return false; } return true; } internal static string[] SplitString(string original) { if (String.IsNullOrEmpty(original)) { return _emptyArray; } var split = from piece in original.Split(',') let trimmed = piece.Trim() where !String.IsNullOrEmpty(trimmed) select trimmed; return split.ToArray(); } } 上的操作中使用它:

AuthorizeAttribute

答案 1 :(得分:1)

创建您自己的黑名单类,就像这样:

public class Blacklist : AuthorizeAttribute {
    private List<string> RolesList;
    public string Roles {
        get {
            string roles = "";
            if (RolesList!= null && RolesList.Count > 0) {
                int counter = 0;
                foreach (string role in RolesList) {
                    counter++;
                    if (counter == RolesList.Count)
                        roles = role;
                    else 
                        roles += role + ",";
                }
            }
            return roles;
        }
        set {
            RolesList = new List<string>();
            string[] roles = value.Split(',');
            foreach (string role in roles) {
                RolesList.Add(role);
            }
        }
    }
//constructor 
    public Blacklist () {
        RolesList = new List<string>();
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext) {
        bool result = true;
        if (httpContext == null) {
            throw new ArgumentNullException("httpContext");
        }
        foreach (string role in RolesList) {
            if (httpContext.User.IsInRole(role)) {
                result = false;
                break;
            }
        }
        return result;
    }
}

现在你将阻止你想要的角色:

[Authorize]
[Blacklist (Roles = "Admin", "Editor")]
    public ActionResult Index() {
    return View();
}