【问题标题】:AllowAnonymous not working with Custom AuthorizationAttributeAllowAnonymous 不使用自定义 AuthorizationAttribute
【发布时间】:2012-11-15 18:03:15
【问题描述】:

这让我困惑了一段时间。显然,常见的类似情况似乎都不适用于这里。我可能错过了一些明显的东西,但我看不到它。

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

我编写了一个继承自 System.Web.Http.AuthorizeAttribute 的自定义授权属性,内容如下:

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

我已将此注册为过滤器:

    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")
        };
    }
}

最常见的情况似乎是混淆了两个 Authorize / AllowAnonymous 属性。 System.Web.Mvc 用于 Web 应用程序,System.Web.Http 用于 WebAPI(无论如何我都理解)。

我使用的两个属性都来自同一个命名空间 - System.Web.Http。我假设这只会继承基本功能并允许我在 OnAuthotize 方法中注入我需要的代码。

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

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

任何想法都会非常感激。

以前有没有人遇到过这个问题并找到了根本原因?

【问题讨论】:

  • 确保使用System.Web.Mvc.AllowAnonymousAttribute 而不是System.Web.Http.AllowAnonymousAttribute。它发生在我身上,三个小时后我意识到了......

标签: asp.net-mvc authentication attributes asp.net-web-api


【解决方案1】:

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 方法的顶部以在找到任何 AllowAnonymous 属性时跳过授权:

if (SkipAuthorization(actionContext)) return;

【讨论】:

  • 在我添加自定义 AuthorizationFilterAttribute 时发现了同样的问题,这解决了。
  • 请注意,此代码具有违反直觉的行为:控制器上的[AllowAnonymous] 属性将覆盖方法上的任何授权属性。为了防止这种情况,您可以针对IAuthorizationFilter(或您正在使用的任何基类/接口)添加另一个自定义属性检查ActionDescriptor,并且仅在匿名控制器为真时跳过身份验证。
  • 没错,但我认为这也是一个设计问题。如果您在同一个控制器上混合使用安全和非安全操作,那么是时候移动一些东西了。
【解决方案2】:

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();
    }

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

【讨论】:

  • 用户请求 web api 行为,而不是 mvc。
  • @LeandroTupone:当您在代码中使用 AllowAnonymousAttribute 而不是引用 System.Web.Mvc 时,请使用 System.Web.Http;那么应该没问题。
  • 我来到这里希望我可以将海报问题改编为我在 MVC 中遇到的相同问题。感谢这个答案,让您满意。
【解决方案3】:

就我而言,上述解决方案均无效。 我正在使用带有自定义 IAuthorizationFilter 的 .Net Core 3.1,我必须执行以下操作:

public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any()) return;

【讨论】:

    【解决方案4】:

    使用 MVC 5
    解决此问题的步骤:-
    1. 更新你的 WebAPI 项目的 Anonymous 属性,让它喜欢

    [System.Web.Mvc.AllowAnonymous]
    
    1. 现在转到您的自定义属性类并编写代码

       public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext filterContext)
      {
          if (filterContext == null)
          {
              throw new UnauthorizedAccessException("Access Token Required");
          }
          base.OnAuthorization(filterContext);
          if (filterContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
          {
              return;
          }
          if (filterContext.Request.Headers.Authorization != null)
          {
              var response = 
       PTPRestClient.GetRequest(filterContext.Request.Headers.Authorization.ToString(), 
       "api/validate/validate-request");
              if (!response.IsSuccessStatusCode)
              {
                  throw new UnauthorizedAccessException();
              }
      
      
          }
          else
          {
              throw new UnauthorizedAccessException("Access Token Required");
          }
      }
      

    【讨论】:

      【解决方案5】:

      这是针对 ASP.NET Core 2+ 和 ASP.NET Core 3+ 的解决方案。 将其添加到 IAsyncAuthorizationFilter 实现中:

      private static bool HasAllowAnonymous(AuthorizationFilterContext context)
      {
          var filters = context.Filters;
          return filters.OfType<IAllowAnonymousFilter>().Any();
      }
      

      然后像这样检查:

      public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
      {
          if(HasAllowAnonymous(context))
              return;
      }
      

      【讨论】:

        【解决方案6】:

        使用 C#6.0 创建一个扩展 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 将能够调用扩展方法,只需确保它们在同一个命名空间中,或者包含正确的 using 语句。

        [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*/
            }
        }
        

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:
            public class MyAuthorizationAuthorize : AuthorizeAttribute, IAuthorizationFilter
            {
            public override void OnAuthorization(AuthorizationContext filterContext)
                    {
                        if (filterContext.HttpContext.Request.IsAuthenticated)
                        {
                            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
                                filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
            
                            if (skipAuthorization) return;
            
                        }
                        else filterContext.Result = new HttpUnauthorizedResult();
                    }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-10-19
              • 2013-11-09
              • 2015-02-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-06
              • 1970-01-01
              相关资源
              最近更新 更多