Asp.net mvc AllowAnonymous不使用自定义AuthorizationAttribute

Asp.net mvc AllowAnonymous不使用自定义AuthorizationAttribute,asp.net-mvc,authentication,attributes,asp.net-web-api,Asp.net Mvc,Authentication,Attributes,Asp.net Web Api,这让我困惑了一段时间。通常遇到的类似情况在这里似乎都不适用。我可能错过了一些明显的东西,但我看不到 在我的Mvc Web应用程序中,我使用Authorize和AllowAnonymous属性,这样您就必须显式地公开一个操作,而不是锁定站点的安全区域。我更喜欢这种方法。然而,我无法在我的WebAPI中获得相同的行为 我编写了一个自定义授权属性,该属性继承自System.Web.Http.AuthorizeAttribute,具有以下内容: [AttributeUsage(AttributeTarg

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

在我的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 void OnAuthorization(AuthorizationFilterContext context)
    {
        if (context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any()) return;
我已将其注册为筛选器:

    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);
任何想法都将不胜感激


以前是否有人遇到过此问题并找到了根本原因?

在authorized属性中有以下代码:

private static bool SkipAuthorization(HttpActionContext actionContext)
{
    Contract.Assert(actionContext != null);

    return actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()
               || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
}

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:

使用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();
    }
}
现在,您的override 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*/
    }
}

我必须使用不同版本的.net framework或web api,但希望这能帮助某些人:

        bool skipAuthorization = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
        if (skipAuthorization)
        {
            return;
        }
bool skipAuthorization=actionContext.ActionDescriptor.GetCustomAttributes().Any()| | actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes().Any();
如果(授权)
{
返回;
}
使用MVC5
克服此问题的步骤:-
1.更新WebAPI项目的匿名属性并使其类似

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

     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");
        }
    }
    
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext filterContext)
    {
    如果(filterContext==null)
    {
    抛出新的UnauthorizedAccessException(“需要访问令牌”);
    }
    基于授权(filterContext);
    if(filterContext.ActionDescriptor.GetCustomAttributes().Any())
    {
    返回;
    }
    if(filterContext.Request.Headers.Authorization!=null)
    {
    var响应=
    PTPRestClient.GetRequest(filterContext.Request.Headers.Authorization.ToString(),
    “api/验证/验证请求”);
    如果(!response.issucessStatusCode)
    {
    抛出新的UnauthorizedAccessException();
    }
    }
    其他的
    {
    抛出新的UnauthorizedAccessException(“需要访问令牌”);
    }
    }
    

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

    私有静态bool具有AllowAnonymous(授权筛选器上下文)
    {
    var filters=context.filters;
    返回filters.OfType().Any();
    }
    
    检查如下:

    AuthorizationAsync(AuthorizationFilterContext上下文)上的公共异步任务 { if(HasAllowAnonymous(上下文)) 返回; }
    在我的例子中,上述解决方案都不起作用。 我将.Net Core 3.1与自定义的
    iaAuthorizationFilter
    一起使用,我必须执行以下操作:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class MyAuthorizationAttribute : System.Web.Http.AuthorizeAttribute
    
    public void OnAuthorization(AuthorizationFilterContext context)
        {
            if (context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any()) return;
    
    authorization上的公共无效(AuthorizationFilterContext上下文)
    {
    if(context.ActionDescriptor.EndpointMetadata.OfType().Any())返回;
    
    用户要求的是web api行为,而不是mvc。@LeandroTupone:当您在代码中使用AllowAnonymousAttribute而不是引用System.web.mvc时,请使用System.web.Http;然后就可以了。我来这里是希望能够将海报问题与我在mvc中遇到的问题相适应。由于这个答案,您会感到满意。请确保使用
     System.Web.Mvc.AllowAnonymousAttribute
    而不是
    System.Web.Http.AllowAnonymousAttribute
    。这发生在我身上,三个小时后我意识到了这一点……当我添加自定义授权筛选器属性时发现了同样的问题,并解决了它。请注意,此代码具有违反直觉的行为:
    [AllowAnonymous]控制器上的
    属性将覆盖该方法上的任何授权属性。为了防止这种情况,您可以针对
    IAuthorizationFilter
    (或您正在使用的任何基类/接口)为
    ActionDescriptor
    添加另一个自定义属性检查只有当匿名控制器为真时,如果验证为假,才跳过验证。是的,但我认为这也是一个设计问题。如果在同一个控制器上混合了安全和非安全操作,那么是时候改变一下了。