如何模拟AllowAnonymousAttribute行为?

时间:2015-09-13 18:18:02

标签: asp.net-mvc authorization custom-attributes authorize-attribute

我想实现一个默认应用[Authorize(Roles = "Admin")]属性的白名单方法。然后,我想在列入白名单的操作中指定[AllowAnonymous][AllowMember]

所以我需要创建一个类似于AllowAnonymous的属性,但只允许访问“Member”角色。 (与AllowAnonymous一样,它应该覆盖可能在控制器上作为全局过滤器生效的任何Authorize属性。)

我最初尝试从AllowAnonymousAttribute继承,但我发现它已被封存。我用谷歌搜索“继承允许匿名”但答案让我脱离了我的深度。

我的方法是否明智,我如何创建这样的属性?

更新

按照NightOwl888的建议和this page的一些代码,我有:

  1. 创建了两个Attributes,一个允许成员,另一个是公共

  2. 继承AuthorizeAttribute以创建一个新的 申请作为全球过滤器

  3. 在AuthorizeCore()方法中插入了几个方法,检查属性并返回true

  4. 我希望我在下面的代码中没有做任何愚蠢的事情......如果它看起来不错(或者没有),我会很感激。

    感谢。

    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 个答案:

答案 0 :(得分:1)

AllowAnonymous属性的所有行为都是coded into the AuthorizeAttribute.OnAuthorize method。因此,如果您想重用此行为,最好的方法是继承AuthorizeAttribute并覆盖AuthorizeCore method