Как эмулировать поведение AllowAnonymousAttribute?

Я хотел бы реализовать подход белого списка, который будет применять [Authorize(Roles = "Admin")] атрибут по умолчанию. Тогда я бы хотел уточнить [AllowAnonymous] или же [AllowMember] на белый список действий.

Поэтому мне нужно создать атрибут, похожий на AllowAnonymous, но только предоставляя доступ роли "Участник". (Подобно AllowAnonymousследует переопределить любой Authorize атрибуты, которые могут действовать на контроллеры как глобальные фильтры.)

Я изначально пытался унаследовать от AllowAnonymousAttribute, но я нахожу это запечатанным. Я гуглил "Inherit allowanonymous", но ответы находят меня вне моей глубины.

Я мудр в своем подходе, и как я могу создать такой атрибут?


Обновить

Следуя совету NightOwl888 и некоторому коду с этой страницы, у меня есть:

  1. Создано два Attributesодин для членов, другой для публики

  2. Унаследовал атрибут AuthorizeAttribute, чтобы создать новый, который я буду применять в качестве глобального фильтра.

  3. Вставил несколько методов в метод 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 метод вместо.

Другие вопросы по тегам