Как эмулировать поведение AllowAnonymousAttribute?
Я хотел бы реализовать подход белого списка, который будет применять [Authorize(Roles = "Admin")]
атрибут по умолчанию. Тогда я бы хотел уточнить [AllowAnonymous]
или же [AllowMember]
на белый список действий.
Поэтому мне нужно создать атрибут, похожий на AllowAnonymous
, но только предоставляя доступ роли "Участник". (Подобно AllowAnonymous
следует переопределить любой Authorize
атрибуты, которые могут действовать на контроллеры как глобальные фильтры.)
Я изначально пытался унаследовать от AllowAnonymousAttribute
, но я нахожу это запечатанным. Я гуглил "Inherit allowanonymous", но ответы находят меня вне моей глубины.
Я мудр в своем подходе, и как я могу создать такой атрибут?
Обновить
Следуя совету NightOwl888 и некоторому коду с этой страницы, у меня есть:
Создано два
Attributes
один для членов, другой для публикиУнаследовал атрибут AuthorizeAttribute, чтобы создать новый, который я буду применять в качестве глобального фильтра.
Вставил несколько методов в метод AuthorizeCore(), которые проверяют атрибуты и возвращают true
Я надеюсь, что я не делаю ничего глупого в приведенном ниже коде... Я был бы признателен за головку (или вниз), если она выглядит нормально (или нет).
Благодарю.
namespace FP.Codebase.Attributes
{
public class AllowPublicAccessAttribute : Attribute
{}
public class AllowMemberAccessAttribute : Attribute
{}
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.HttpContext.Items["ActionDescriptor"] = filterContext.ActionDescriptor;
base.OnAuthorization(filterContext);
}
private bool IsAllowPublicAccessAttributeAppliedToAction(ActionDescriptor actionDescriptor)
{
return (actionDescriptor.IsDefined(typeof(AllowPublicAccessAttribute), inherit: true)
|| actionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowPublicAccessAttribute), inherit: true));
}
private bool IsAllowMemberAccessAttributeAppliedToAction(ActionDescriptor actionDescriptor)
{
return (actionDescriptor.IsDefined(typeof(AllowMemberAccessAttribute), inherit: true)
|| actionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowMemberAccessAttribute), inherit: true));
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var actionDescriptor = httpContext.Items["ActionDescriptor"] as ActionDescriptor;
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
IPrincipal user = httpContext.User;
if (IsAllowPublicAccessAttributeAppliedToAction(actionDescriptor))
{
return true;
}
if (IsAllowMemberAccessAttributeAppliedToAction(actionDescriptor) && user.IsInRole("Member"))
{
return true;
}
if (!user.Identity.IsAuthenticated)
{
return false;
}
var _usersSplit = SplitString(Users);
var _rolesSplit = SplitString(Roles);
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;
}
// copied from https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/AuthorizeAttribute.cs
internal static string[] SplitString(string original)
{
if (String.IsNullOrEmpty(original))
{
return new string[0];
}
var split = from piece in original.Split(',')
let trimmed = piece.Trim()
where !String.IsNullOrEmpty(trimmed)
select trimmed;
return split.ToArray();
}
}
}
1 ответ
Все о поведении AllowAnonymous
атрибут закодирован в AuthorizeAttribute.OnAuthorize
метод. Итак, если вы хотите повторно использовать это поведение, лучший подход заключается в наследовании AuthorizeAttribute
и переопределить AuthorizeCore
метод вместо.