Ich versuche, die Authentifizierung für einen in WCF implementierten und in Azure gehosteten REST-Service zu implementieren. Ich verwende HttpModule, um die AuthenticationRequest-, PostAuthenticationRequest- und EndRequest-Ereignisse zu verarbeiten. Wenn der Authorization-Header fehlt oder das darin enthaltene Token ungültig ist, setze ich während der EndRequest den StatusCode auf die Response to 401. Ich habe jedoch festgestellt, dass EndRequest zweimal aufgerufen wird, und beim zweiten Aufruf hat die Antwort bereits Header set, wodurch der Code, der den StatusCode setzt, eine Ausnahme auslöst.
Ich habe Sperren zu Init () hinzugefügt, um sicherzustellen, dass der Handler nicht zweimal registriert wurde; lief noch zweimal. Init () lief auch zweimal, was darauf hinweist, dass zwei Instanzen des HttpModule erstellt wurden. Die Verwendung von Set Object ID in dem VS-Debugger scheint jedoch anzuzeigen, dass die Anforderungen tatsächlich unterschiedliche Anforderungen sind. Ich habe in Fiddler verifiziert, dass vom Browser nur eine Anfrage an meinen Dienst gestellt wird.
Wenn ich zur Verwendung von global.asax-Routing statt von der WCF-Service-Host-Konfiguration wechseln möchte, wird der Handler nur einmal aufgerufen und alles funktioniert einwandfrei.
Wenn ich dem Konfigurationsabschnitt system.web sowie dem Konfigurationsabschnitt system.webServer in der Datei Web.config eine Konfiguration hinzufüge, wird der Handler nur einmal aufgerufen, und alles funktioniert einwandfrei.
Also habe ich Abschwächungen, aber ich mag Verhalten, das ich nicht verstehe. Warum wird der Handler zweimal aufgerufen?
Hier ist eine minimale Wiederholung des Problems:
Web.config:
%Vor%Http-Modul:
%Vor%Entschuldigung keine Ahnung, warum es zweimal aufgerufen werden konnte, jedoch kann EndRequest aus mehreren Gründen aufgerufen werden. Anfrage beendet, Anfrage wurde abgebrochen, ein Fehler ist aufgetreten. Also würde ich nicht darauf vertrauen, dass wenn du da bist, du tatsächlich eine 401 hast, könnte es aus anderen Gründen sein.
Ich würde nur meine Logik in der AuthenticateRequest-Pipeline behalten:
%Vor% Wenn eine ASP.net-Anwendung gestartet wird, um die Leistung zu maximieren, instanziiert der ASP.NET Worker-Prozess so viele HttpApplication
-Objekte, wie er benötigt. Jedes HttpApplication
-Objekt, instanziiert auch eine Kopie jedes IHttpModule
, das registriert ist, und ruft die Init-Methode auf! Das ist wirklich ein internes Design des ASP.NET-Prozesses, der unter IIS läuft (oder cassini, der VS im Webserver eingebaut ist). Kann sein, weil Ihre ASPX-Seite Links zu anderen Ressourcen enthält, die Ihr Browser herunterladen wird, eine externe Ressource und einen Iframe, eine CSS-Datei oder möglicherweise ASP.NET Worker Process-Verhalten.
Glücklicherweise ist das bei Global.asax nicht der Fall:
Die Methoden Application_Start und Application_End sind spezielle Methoden Diese repräsentieren keine HttpApplication-Ereignisse. ASP.NET ruft sie einmal auf für die Lebensdauer der Anwendungsdomäne, nicht für jeden HttpApplication-Instanz.
Allerdings wird HTTPModule's init
method einmal für jede Instanz der HttpApplication-Klasse aufgerufen, nachdem alle Module erstellt wurden
Das erste Mal, dass eine ASP.NET-Seite oder ein ASP.NET-Prozess in einem Anwendung wird eine neue Instanz von HttpApplication erstellt. Jedoch, um Maximierung der Leistung, für die HttpApplication-Instanzen möglicherweise wiederverwendet werden mehrere Anfragen.
Und durch das folgende Diagramm illustriert:
Wenn Sie möchten, dass Code nur einmal ausgeführt wird, können Sie entweder Application_Start
von Global.asax
verwenden oder ein Flag setzen und im zugrunde liegenden Modul sperren, was meiner Meinung nach keine gute Übung ist der Authentifizierung!