AllowAnonymous不能使用Custom AuthorizationAttribute

这让我难住了一段时间。 没有遇到类似的情况似乎在这里显然适用。 我可能错过了一些明显的东西,但是我看不见它。

在我的Mvc Web应用程序中,我使用Authorize和AllowAnonymous属性,以便您必须明确地公开可用的操作,而不是locking网站的安全区域。 我更喜欢这种方法。 但是我无法在WebAPI中获得相同的行为。

我写了一个自定义的授权属性从System.Web.Http.AuthorizeAttributeinheritance与以下:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class MyAuthorizationAttribute : System.Web.Http.AuthorizeAttribute 

我把这个注册为一个filter:

  public static void RegisterHttpFilters(HttpFilterCollection filters) { filters.Add(new MyAuthorizationAttribute()); } 

这一切都按预期工作,没有凭据,操作不再可用。 问题是,现在下面的方法将不允许AllowAnonymous属性做它的事情:

 [System.Web.Http.AllowAnonymous] public class HomeController : ApiController { [GET("/"), System.Web.Http.HttpGet] public Link[] Index() { return new Link[] { new SelfLink(Request.RequestUri.AbsoluteUri, "api-root"), new Link(LinkRelConstants.AuthorizationEndpoint, "OAuth/Authorize/", "authenticate"), new Link(LinkRelConstants.AuthorizationTokenEndpoint , "OAuth/Tokens/", "auth-token-endpoint") }; } } 

最常见的情况似乎是将两个授权/允许匿名属性混合在一起。 System.Web.Mvc适用于Web应用程序,System.Web.Http适用于WebAPI(据我所知)。

我使用的两个属性都来自同一个命名空间 – System.Web.Http。 我认为这只会inheritance基本function,并允许我在OnAuthotize方法中注入所需的代码。

根据文档,AllowAnonymous属性在我立即调用的OnAuthorize方法内工作:

  public override void OnAuthorization(HttpActionContext actionContext) { base.OnAuthorization(actionContext); 

任何想法将非常感激。

有没有人遇到过这个问题,并find根本原因?

在AuthorizeAttribute中有以下代码:

 private static bool SkipAuthorization(HttpActionContext actionContext) { Contract.Assert(actionContext != null); return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any() || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); } 

将此方法包含在您的AuthorizeAttribute类中,然后将以下内容添加到OnAuthorization方法的顶部,以便在find任何AllowAnonymous属性时跳过授权:

 if (SkipAuthorization(actionContext)) return; 

ASP.NET MVC 4:

 bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true); 

要么

  private static bool SkipAuthorization(AuthorizationContext filterContext) { Contract.Assert(filterContext != null); return filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any() || filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any(); } 

Soruce: http ://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-global-authentication-and-allow-anonymous

使用C#6.0创build一个扩展ActionExecutingContext的静态类。

 public static class AuthorizationContextExtensions { public static bool SkipAuthorization(this ActionExecutingContext filterContext) { Contract.Assert(filterContext != null); return filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any()|| filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any(); } } 

现在你的覆盖filterContext将能够调用扩展方法,只要确保它们在相同的命名空间,或包括正确的使用语句。

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class AuthorizeCustomAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.SkipAuthorization()) return;// CALL EXTENSION METHOD /*NOW DO YOUR LOGIC FOR NON ANON ACCESS*/ } } 

我必须使用.net框架或web api的不同版本,但希望这可以帮助某人:

  bool skipAuthorization = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); if (skipAuthorization) { return; }