Ich habe ein seltsames Problem mit der Verwendung der Owin-Cookie-Authentifizierung.
Wenn ich meine IIS-Serverauthentifizierung starte, funktioniert sie unter IE / Firefox und Chrome einwandfrei.
Ich habe angefangen, einige Tests mit Authentifizierung durchzuführen und mich auf verschiedenen Plattformen anzumelden, und bin auf einen seltsamen Fehler gestoßen. Sporadisch sendet das Owin Framework / IIS einfach keine Cookies an die Browser. Ich werde einen Benutzernamen und ein Passwort eingeben, die korrekt sind. Der Code wird ausgeführt, aber es wird überhaupt kein Cookie an den Browser gesendet. Wenn ich den Server neu starte, funktioniert er. Irgendwann werde ich versuchen, mich anzumelden, und erneut werden keine Cookies mehr geliefert. Das Überschreiten des Codes bewirkt nichts und wirft keine Fehler auf.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true,
AuthenticationType = "ABC",
LoginPath = new PathString("/Account/Login"),
CookiePath = "/",
CookieName = "ABC",
Provider = new CookieAuthenticationProvider
{
OnApplyRedirect = ctx =>
{
if (!IsAjaxRequest(ctx.Request))
{
ctx.Response.Redirect(ctx.RedirectUri);
}
}
}
});
Und innerhalb meines Anmeldevorgangs habe ich den folgenden Code:
IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var authentication = HttpContext.Current.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("ABC");
identity.AddClaim(new Claim(ClaimTypes.Name, user.Username));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.User_ID.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Role, role.myRole.ToString()));
authentication.AuthenticationResponseGrant =
new AuthenticationResponseGrant(identity, new AuthenticationProperties()
{
IsPersistent = isPersistent
});
authenticationManager.SignIn(new AuthenticationProperties() {IsPersistent = isPersistent}, identity);
Update 1: Es scheint, dass eine Ursache des Problems darin besteht, dass beim Hinzufügen von Elementen zur Sitzung die Probleme beginnen. Das Hinzufügen von etwas Einfachem wie Session.Content["ABC"]= 123
scheint das Problem zu schaffen.
Was ich erkennen kann, ist Folgendes: 1) (Chrome) Wenn ich mich anmelde, erhalte ich ASP.NET_SessionId + mein Authentifizierungscookie. 2) Ich gehe zu einer Seite, auf der eine Sitzung festgelegt wird. Inhalt ... 3) Öffnen Sie einen neuen Browser (Firefox) und versuchen Sie sich anzumelden. Es wird weder eine ASP.NET_SessionId empfangen noch ein Authentifizierungs-Cookie hat die ASP.NET_SessionId, die weiterhin funktioniert. Sobald ich dieses Cookie entferne, hat es das gleiche Problem wie alle anderen Browser, an denen ich an der IP-Adresse (10.xxx) und dem lokalen Host arbeite.
Update 2:ASPNET_SessionId
Erzwinge die Erstellung von zuerst auf meiner login_load-Seite vor der Authentifizierung mit OWIN.
1) Bevor ich mich bei OWIN authentifiziere, mache ich Session.Content
auf meiner Anmeldeseite einen zufälligen Wert, um die ASP.NET_SessionId zu starten. 2) Dann authentifiziere ich mich und führe weitere Sitzungen durch. 3) Andere Browser scheinen jetzt zu funktionieren
Das ist bizarr. Ich kann nur schlussfolgern, dass dies etwas mit ASP und OWIN zu tun hat, die glauben, dass sie sich in verschiedenen Bereichen befinden oder so ähnlich.
Update 3 - Seltsames Verhalten zwischen den beiden.
Zusätzliches seltsames Verhalten festgestellt - Timeout der Owin- und ASP-Sitzung ist unterschiedlich. Was ich sehe, ist, dass meine Owin-Sitzungen durch einen Mechanismus länger am Leben bleiben als meine ASP-Sitzungen. Also beim Anmelden: 1.) Ich habe eine Cookie-basierte Authentifizierungssitzung 2.) Ich habe einige Sitzungsvariablen festgelegt
Meine Sitzungsvariablen (2) "sterben", bevor die Sitzungsvariable owin cookie eine erneute Anmeldung erzwingt, was zu unerwartetem Verhalten in meiner gesamten Anwendung führt. (Person ist angemeldet, aber nicht wirklich angemeldet)
Update 3B
Nach einigem Graben sah ich einige Kommentare auf einer Seite, die besagten, dass das Zeitlimit für die "Formular" -Authentifizierung und das Sitzungszeitlimit übereinstimmen müssen. Ich denke normalerweise, dass die beiden synchron sind, aber aus irgendeinem Grund sind die beiden nicht synchron.
Zusammenfassung der Problemumgehungen
1) Erstellen Sie vor der Authentifizierung immer zuerst eine Sitzung. Erstellen Sie grundsätzlich eine Sitzung, wenn Sie die Anwendung startenSession["Workaround"] = 0;
2) [Experimentell] Wenn Sie Cookies beibehalten, stellen Sie sicher, dass Ihr OWIN-Zeitlimit / Ihre Länge länger ist als Ihr sessionTimeout in Ihrer web.config (beim Testen).
quelle
Antworten:
Ich bin auf dasselbe Problem gestoßen und habe die Ursache auf die Implementierung des OWIN ASP.NET-Hostings zurückgeführt. Ich würde sagen, es ist ein Fehler.
Einige Hintergrundinformationen
Meine Ergebnisse basieren auf diesen Baugruppenversionen:
OWIN verwendet eine eigene Abstraktion, um mit Antwort-Cookies ( Microsoft.Owin.ResponseCookieCollection ) zu arbeiten. Diese Implementierung umschließt die Sammlung der Antwortheader direkt und aktualisiert den Set-Cookie- Header entsprechend. Der OWIN ASP.NET-Host ( Microsoft.Owin.Host.SystemWeb ) umschließt nur System.Web.HttpResponse und seine Headersammlung. Wenn also über OWIN ein neues Cookie erstellt wird, wird der Set-Cookie- Header der Antwort direkt geändert.
ASP.NET verwendet jedoch auch eine eigene Abstraktion, um mit Antwort-Cookies zu arbeiten. Dies wird uns als System.Web.HttpResponse.Cookies- Eigenschaft zur Verfügung gestellt und von der versiegelten Klasse System.Web.HttpCookieCollection implementiert . Diese Implementierung umschließt den Set-Cookie- Header der Antwort nicht direkt, sondern verwendet einige Optimierungen und eine Handvoll interner Benachrichtigungen, um den geänderten Status des Antwortobjekts zu manifestieren.
Dann gibt es einen Punkt spät in der Anforderungslebensdauer, an dem der geänderte Status von HttpCookieCollection getestet wird ( System.Web.HttpResponse.GenerateResponseHeadersForCookies () ) und Cookies in den Set-Cookie- Header serialisiert werden . Wenn sich diese Sammlung in einem bestimmten Zustand befindet, wird der gesamte Set-Cookie-Header zuerst gelöscht und aus den in der Sammlung gespeicherten Cookies neu erstellt.
Die Implementierung der ASP.NET-Sitzung verwendet die System.Web.HttpResponse.Cookies- Eigenschaft, um das Cookie ASP.NET_SessionId zu speichern. Außerdem gibt es einige grundlegende Optimierungen im ASP.NET-Sitzungsstatusmodul ( System.Web.SessionState.SessionStateModule ), die über die statische Eigenschaft s_sessionEverSet implementiert wurden und selbsterklärend sind. Wenn Sie jemals etwas für den Sitzungsstatus in Ihrer Anwendung speichern, erledigt dieses Modul für jede Anforderung etwas mehr Arbeit.
Zurück zu unserem Login-Problem
Mit all diesen Stücken können Ihre Szenarien erklärt werden.
Fall 1 - Sitzung wurde nie festgelegt
System.Web.SessionState.SessionStateModule , s_sessionEverSet-Eigenschaft ist false. Vom Sitzungsstatusmodul werden keine Sitzungs-IDs generiert, und der System.Web.HttpResponse.Cookies- Erfassungsstatus wird nicht als geändert erkannt . In diesem Fall werden OWIN-Cookies korrekt an den Browser gesendet und die Anmeldung funktioniert.
Fall 2 - Die Sitzung wurde irgendwo in der Anwendung verwendet, jedoch nicht, bevor der Benutzer versucht, sich zu authentifizieren
System.Web.SessionState.SessionStateModule , s_sessionEverSet-Eigenschaft ist true. Sitzungs- IDs werden von SessionStateModule generiert . ASP.NET_SessionId wird zur System.Web.HttpResponse.Cookies- Auflistung hinzugefügt, aber später in der Anforderungslebensdauer entfernt, da die Sitzung des Benutzers tatsächlich leer ist. In diesem Fall wird der Erfassungsstatus von System.Web.HttpResponse.Cookies als geändert erkannt und der Set-Cookie- Header wird zuerst gelöscht, bevor Cookies auf den Header-Wert serialisiert werden.
In diesem Fall gehen OWIN-Antwortcookies "verloren" und der Benutzer wird nicht authentifiziert und zur Anmeldeseite zurückgeleitet.
Fall 3 - Sitzung wird verwendet, bevor der Benutzer versucht, sich zu authentifizieren
System.Web.SessionState.SessionStateModule , s_sessionEverSet-Eigenschaft ist true. Sitzungs- IDs werden von SessionStateModule generiert . ASP.NET_SessionId wird zu System.Web.HttpResponse.Cookies hinzugefügt . Aufgrund der internen Optimierung in System.Web.HttpCookieCollection und System.Web.HttpResponse.GenerateResponseHeadersForCookies () wird der Set-Cookie-Header NICHT zuerst gelöscht, sondern nur aktualisiert.
In diesem Fall werden sowohl OWIN-Authentifizierungscookies als auch ASP.NET_SessionId-Cookies als Antwort gesendet und die Anmeldung funktioniert.
Allgemeineres Problem mit Cookies
Wie Sie sehen, ist das Problem allgemeiner und nicht auf die ASP.NET-Sitzung beschränkt. Wenn Sie OWIN über Microsoft.Owin.Host.SystemWeb hosten und Sie / etwas die System.Web.HttpResponse.Cookies- Sammlung direkt verwenden , sind Sie gefährdet.
Zum Beispiel funktioniert dies und beide Cookies werden korrekt an den Browser gesendet ...
Aber dies bedeutet nicht und OwinCookie „verloren“ ...
Beide wurden von VS2013, IISExpress und der Standard-MVC-Projektvorlage getestet.
quelle
Beginnend mit der großartigen Analyse von @TomasDolezal habe ich mir sowohl die Owin- als auch die System.Web-Quelle angesehen.
Das Problem ist, dass System.Web über eine eigene Hauptquelle für Cookie-Informationen verfügt und dies nicht der Set-Cookie-Header ist. Owin kennt nur den Set-Cookie-Header. Eine Problemumgehung besteht darin, sicherzustellen, dass alle von Owin gesetzten Cookies auch in der
HttpContext.Current.Response.Cookies
Sammlung gesetzt werden.Ich habe eine kleine Middleware ( Quelle , Nuget ) erstellt, die genau das tut und die unmittelbar über der Registrierung der Cookie-Middleware platziert werden soll.
quelle
app.UseKentorCookieMiddlewareSaver();
in Startup.Auth.cs aktivieren . Es sollte auch das Löschen von Abmeldecookies übernehmen.app.UseKentorOwinCookieSaver()
und möglicherweise in Ihrer ursprünglichen Antwort wie auf der GitHub-Seite des Pakets enthalten zu sein .Kurz gesagt, der .NET-Cookie-Manager gewinnt den OWIN-Cookie-Manager und überschreibt die auf der OWIN-Ebene festgelegten Cookies . Das Update besteht darin, die SystemWebCookieManager-Klasse zu verwenden, die hier als Lösung für das Katana-Projekt bereitgestellt wird . Sie müssen diese oder eine ähnliche Klasse verwenden, wodurch OWIN gezwungen wird, den .NET-Cookie-Manager zu verwenden, damit keine Inkonsistenzen auftreten :
Weisen Sie es beim Start Ihrer Anwendung einfach zu, wenn Sie Ihre OWIN-Abhängigkeiten erstellen:
Eine ähnliche Antwort wurde hier gegeben, enthält jedoch nicht die gesamte Codebasis, die zur Lösung des Problems erforderlich ist. Ich sehe daher die Notwendigkeit, sie hier hinzuzufügen, da der externe Link zum Katana-Projekt möglicherweise ausfällt und dies vollständig aufgezeichnet werden sollte auch hier als Lösung.
quelle
ASP.NET Webforms, OWIN, ADFS
Startup.ConfigureAuth
wirapp.UseCookieAuthentication
undapp.UseWsFederationAuthentication
und schließlichapp.UseStageMarker
Das Katana-Team antwortete auf das von Tomas Dolezar angesprochene Problem und veröffentlichte Dokumentationen zu Problemumgehungen :
Siehe SystemWebCookieManager-Implementierung in der Dokumentation (Link oben)
Weitere Informationen hier
Bearbeiten
Nachfolgend finden Sie die Schritte, die wir zur Lösung des Problems unternommen haben. Sowohl 1. als auch 2. haben das Problem auch separat gelöst, aber wir haben beschlossen, beide nur für den Fall anzuwenden:
1. Verwenden Sie SystemWebCookieManager
2. Legen Sie die Sitzungsvariable fest:
(Randnotiz: Die obige Initialize-Methode ist der logische Ort für den Fix, da base.Initialize Session verfügbar macht. Der Fix kann jedoch auch später angewendet werden, da in OpenId zuerst eine anonyme Anforderung vorliegt, dann zum OpenId-Anbieter umgeleitet und dann zurück Die Probleme treten nach der Rückleitung zur App auf, während der Fix die Sitzungsvariable bereits während der ersten anonymen Anforderung festlegt, wodurch das Problem behoben wird, bevor überhaupt eine Rückleitung erfolgt.
Bearbeiten 2
Kopieren und Einfügen aus dem Katana-Projekt 14.05.2016:
Füge das hinzu:
...und das:
quelle
ControllerContext.HttpContext.Session.RemoveAll();
in IhreExternalLogin()
Aktion ein, bevor Sie anrufenChallengeResult()
. Ich weiß nicht, ob es die beste Lösung ist, aber es ist die einfachste.?.
(null-bedingte Operator) nur in C # 6 funktioniert.Es wurden bereits Antworten bereitgestellt, aber in Version 3.1.0 gibt es eine SystemWebChunkingCookieManager-Klasse, die verwendet werden kann.
https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs
https://raw.githubusercontent.com/aspnet/AspNetKatana/c33569969e79afd9fb4ec2d6bdff877e376821b2/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs
quelle
Wenn Sie selbst Cookies in der OWIN-Middleware setzen,
OnSendingHeaders
scheint die Verwendung das Problem zu umgehen.Beispielsweise wird die Verwendung des folgenden Codes
owinResponseCookie2
festgelegt, obwohl diesowinResponseCookie1
nicht der Fall ist:quelle
Ich hatte ein ähnliches Problem mit Visual Studio 2017 und .net MVC 5.2.4 . Das Aktualisieren von Nuget Microsoft.Owin.Security.Google auf die neueste Version, die derzeit 4.0.1 ist, hat für mich funktioniert! Hoffe das hilft jemandem!
quelle
Die schnellste einzeilige Codelösung:
Fügen Sie einfach diese Zeile vor der CreateIdentity-Methode hinzu:
quelle
HttpContext.Current.Session["RunSession"] = "1";
? in Globa.asaxSession_Start
?Ich hatte das gleiche Symptom, dass der Set-Cookie-Header nicht gesendet wurde, aber keine dieser Antworten half mir. Alles funktionierte auf meinem lokalen Computer, aber wenn es für die Produktion bereitgestellt wurde, wurden die Set-Cookie-Header niemals gesetzt.
Es stellte sich heraus, dass es sich um eine Kombination aus der Verwendung eines benutzerdefinierten
CookieAuthenticationMiddleware
Programms mit WebApi und der Unterstützung der WebApi-Komprimierung handelteZum Glück habe ich ELMAH in meinem Projekt verwendet, wodurch ich diese Ausnahme protokollieren konnte:
Was mich zu diesem GitHub-Problem führte
Wenn Sie ein seltsames Setup wie das meine haben, sollten Sie die Komprimierung für Ihre WebApi-Controller / -Methoden, die Cookies setzen, deaktivieren oder das ausprobieren
OwinServerCompressionHandler
.quelle