ASP.NET Roles/Users 的 MVC 黑名单
ASP.NET MVC Blacklist for Roles/Users
问题摘要:在 ASP.NET MVC 中,是否有一种干净的方法来防止特定用户或角色访问操作?
显然,以下将允许角色 Admin
和 Editor
访问整个控制器。
[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();
}
}
有没有一种方法可以在不列出 需要 访问权限的每个角色的情况下完成此操作,并且只指定应该 阻止 的角色无法访问?
这是我用来解决这个问题的 class 的代码。它很大程度上源自 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
:
[Authorize(Roles = "Admin, Editor")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[BlackList(Roles = "Editor")]
public ActionResult About()
{
return View();
}
}
像这样创建自己的黑名单class:
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();
}
问题摘要:在 ASP.NET MVC 中,是否有一种干净的方法来防止特定用户或角色访问操作?
显然,以下将允许角色 Admin
和 Editor
访问整个控制器。
[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();
}
}
有没有一种方法可以在不列出 需要 访问权限的每个角色的情况下完成此操作,并且只指定应该 阻止 的角色无法访问?
这是我用来解决这个问题的 class 的代码。它很大程度上源自 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
:
[Authorize(Roles = "Admin, Editor")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[BlackList(Roles = "Editor")]
public ActionResult About()
{
return View();
}
}
像这样创建自己的黑名单class:
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();
}