webentwicklung-frage-antwort-db.com.de

AllowAnonymous funktioniert nicht mit Custom AuthorizationAttribute

Das hat mich für eine Weile stumpf gemacht. Offensichtlich scheint keine der häufig anzutreffenden ähnlichen Situationen hier zuzutreffen. Ich habe wahrscheinlich etwas offensichtliches übersehen, kann es aber nicht sehen.

In meiner Mvc-Webanwendung verwende ich die Attribute Authorize und AllowAnonymous so, dass Sie eine Aktion explizit als öffentlich verfügbar öffnen müssen, anstatt die sicheren Bereiche der Site zu sperren. Ich bevorzuge diesen Ansatz sehr. Ich kann jedoch nicht dasselbe Verhalten in meiner WebAPI erhalten.

Ich habe ein benutzerdefiniertes Berechtigungsattribut geschrieben, das von System.Web.Http.AuthorizeAttribute folgende Eigenschaften erbt:

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

Ich habe das als Filter registriert:

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

Das alles funktioniert wie erwartet, Aktionen sind ohne Anmeldeinformationen nicht mehr verfügbar. Das Problem ist, dass nun die folgende Methode das AllowAnonymous-Attribut nicht ausführen kann:

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

Das häufigste Szenario scheint das Vermischen der beiden Attribute Authorize/AllowAnonymous zu sein. System.Web.Mvc steht für Web-Apps und System.Web.Http für WebAPI (so wie ich es sowieso verstehe).

Beide Attribute, die ich verwende, stammen aus demselben Namespace - System.Web.Http. Ich nahm an, dass dies nur die Basisfunktionalität erben und mir erlauben würde, den Code einzufügen, den ich in die OnAuthotize-Methode benötige.

Laut der Dokumentation arbeitet das AllowAnonymous-Attribut in der OnAuthorize-Methode, die ich sofort aufrufe:

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

Jeder Gedanke wäre wirklich dankbar.

Hat jemand dieses Problem schon einmal festgestellt und die Ursache gefunden?

46
Jammer

Im AuthorizeAttribute gibt es folgenden Code:

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

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

Fügen Sie diese Methode in Ihre AuthorizeAttribute-Klasse ein und fügen Sie anschließend der OnAuthorization-Methode Folgendes hinzu, um die Autorisierung zu überspringen, wenn AllowAnonymous-Attribute gefunden werden:

if (SkipAuthorization(actionContext)) return;
77
Jammer

ASP.NET MVC 4:

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

oder

 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

23
g.breeze

Verwenden von C # 6.0 Erstellen Sie eine statische Klasse, die den ActionExecutingContext erweitert.

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

Jetzt kann Ihr override filterContext die Erweiterungsmethode aufrufen. Stellen Sie nur sicher, dass sie sich im selben Namespace befinden, oder schließen Sie die entsprechende using-Anweisung ein.

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

Ich muss eine andere Version des .NET-Frameworks oder der Web-API verwenden, aber hoffentlich hilft dies jemandem:

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

Verwenden von MVC 5
Schritte zur Überwindung dieses Problems: -
1. Aktualisieren Sie Ihr Anonymous-Attribut des WebAPI-Projekts und machen Sie es wie es ist

[System.Web.Mvc.AllowAnonymous]
  1. Gehen Sie jetzt zu Ihrer benutzerdefinierten Attributklasse und schreiben Sie den Code 

     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");
        }
    }
    
0
krishna rajan
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();
        }
}
0
Suvenjeet