ASP.NET_SessionId + OWIN I cookie non vengono inviati al browser


145

Ho uno strano problema con l'utilizzo dell'autenticazione con cookie Owin.

Quando avvio il mio server IIS l'autenticazione funziona perfettamente su IE / Firefox e Chrome.

Ho iniziato a fare alcuni test con autenticazione e accesso su piattaforme diverse e ho riscontrato uno strano errore. Sporadicamente il framework Owin / IIS non invia alcun cookie ai browser. Digiterò un nome utente e una password corretti per l'esecuzione del codice ma nessun cookie viene consegnato al browser. Se riavvio il server inizia a funzionare, ad un certo punto proverò ad accedere e di nuovo i cookie non verranno più consegnati. Il passaggio sul codice non fa nulla e non genera errori.

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

E all'interno della mia procedura di accesso ho il seguente codice:

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

Aggiornamento 1: sembra che una causa del problema sia quando aggiungo elementi alla sessione che iniziano i problemi. L'aggiunta di qualcosa di semplice come Session.Content["ABC"]= 123sembra creare il problema.

Quello che posso capire è il seguente: 1) (Chrome) Quando accedo ottengo ASP.NET_SessionId + il mio cookie di autenticazione. 2) Vado a una pagina che imposta un session.contents ... 3) Apri un nuovo browser (Firefox) e prova ad accedere e non riceve un ASP.NET_SessionId né riceve un cookie di autenticazione 4) Mentre il primo browser ha ASP.NET_SessionId continua a funzionare. Nel momento in cui rimuovo questo cookie ha lo stesso problema di tutti gli altri browser su cui sto lavorando su indirizzo IP (10.xxx) e localhost.

Aggiornamento 2:ASPNET_SessionId imponi la creazione della prima nella mia pagina login_load prima dell'autenticazione con OWIN.

1) prima di autenticarmi con OWIN faccio un casuale Session.Content valore sulla mia pagina di accesso per avviare ASP.NET_SessionId 2) quindi autentico e faccio ulteriori sessioni 3) Altri browser sembrano ora funzionare

Questo è bizzarro. Posso solo concludere che ciò ha a che fare con ASP e OWIN pensando che si trovino in domini diversi o qualcosa del genere.

Aggiornamento 3 - Strano comportamento tra i due.

Ulteriore strano comportamento identificato: il timeout della sessione Owin e ASP è diverso. Quello che sto vedendo è che le mie sessioni Owin rimangono in vita più a lungo delle mie sessioni ASP attraverso un meccanismo. Quindi quando eseguo l'accesso: 1.) Ho una sessione di autenticazione basata su cucinata 2.) Ho impostato alcune variabili di sessione

Le variabili della mia sessione (2) "muoiono" prima che la variabile della sessione del cookie owin imponga di nuovo il login, causando comportamenti imprevisti in tutta la mia applicazione. (La persona è loggata ma non è realmente loggata)

Aggiornamento 3B

Dopo alcuni scavi ho visto alcuni commenti su una pagina che affermano che il timeout di autenticazione dei "moduli" e il timeout della sessione devono corrispondere. Penso normalmente che i due siano sincronizzati, ma per qualsiasi motivo i due non sono sincronizzati.

Riepilogo delle soluzioni alternative

1) Crea sempre una sessione prima dell'autenticazione. Fondamentalmente creare una sessione quando si avvia l'applicazioneSession["Workaround"] = 0;

2) [Sperimentale] se si persistono i cookie assicurarsi che il timeout / lunghezza OWIN sia più lungo della sessioneTimeout nel web.config (in fase di test)


1
Può confermare che l'aggiunta di una chiamata di sessione ad ActionResult Login e ActionResult ExternalLogin ha risolto questo problema. Sono sicuro che ne è necessario solo uno, ma ho entrambi in atto.
Scott,

Grazie! ... L'aggiunta di Session in ExternalLogin ha risolto il problema per me ... questa è magia voodoo ... Ho già perso 6 ore a cercare questo problema ...
xdev

Risposte:


159

Ho riscontrato lo stesso problema e rintracciato la causa dell'implementazione di hosting ASP.NET OWIN. Direi che è un bug.

Qualche sfondo

Le mie scoperte si basano su queste versioni di assembly:

  • Microsoft.Owin, Versione = 2.0.2.0, Cultura = neutro, PublicKeyToken = 31bf3856ad364e35
  • Microsoft.Owin.Host.SystemWeb, Versione = 2.0.2.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35
  • System.Web, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a

OWIN utilizza la propria astrazione per funzionare con i cookie di risposta ( Microsoft.Owin.ResponseCookieCollection ). Questa implementazione avvolge direttamente la raccolta delle intestazioni di risposta e aggiorna di conseguenza l'intestazione Set-Cookie . L'host ASP.NET OWIN ( Microsoft.Owin.Host.SystemWeb ) esegue il wrapping di System.Web.HttpResponse e la sua raccolta di intestazioni. Pertanto, quando viene creato un nuovo cookie tramite OWIN, rispondere Set-Cookie intestazione viene modificata direttamente.

Ma ASP.NET utilizza anche la propria astrazione per funzionare con i cookie di risposta. Questo ci viene esposto come proprietà System.Web.HttpResponse.Cookies e implementato dalla classe sigillata System.Web.HttpCookieCollection . Questa implementazione non racchiude direttamente l'intestazione Set-Cookie di risposta ma utilizza alcune ottimizzazioni e una manciata di notifiche interne per manifestare il suo stato modificato nell'oggetto risposta.

Quindi c'è un punto in ritardo nella durata della richiesta in cui viene testato lo stato modificato di HttpCookieCollection ( System.Web.HttpResponse.GenerateResponseHeadersForCookies () ) e i cookie vengono serializzati nell'intestazione Set-Cookie . Se questa raccolta si trova in uno stato specifico, l'intera intestazione Set-Cookie viene prima cancellata e ricreata dai cookie memorizzati nella raccolta.

L'implementazione della sessione ASP.NET utilizza la proprietà System.Web.HttpResponse.Cookies per archiviare il suo cookie ASP.NET_SessionId. Inoltre c'è qualche ottimizzazione di base nel modulo stato sessione ASP.NET ( System.Web.SessionState.SessionStateModule ) implementato attraverso la proprietà statica denominata s_sessionEverSet che si spiega da sé. Se hai mai archiviato qualcosa nello stato della sessione nella tua applicazione, questo modulo farà un po 'più di lavoro per ogni richiesta.


Torna al nostro problema di accesso

Con tutti questi pezzi i tuoi scenari possono essere spiegati.

Caso 1 - La sessione non è mai stata impostata

System.Web.SessionState.SessionStateModule , la proprietà s_sessionEverSet è falsa. Nessun ID sessione viene generato dal modulo stato sessione e lo stato della raccolta System.Web.HttpResponse.Cookies non viene rilevato come modificato . In questo caso i cookie OWIN vengono inviati correttamente al browser e il login funziona.

Caso 2: la sessione è stata utilizzata da qualche parte nell'applicazione, ma non prima che l'utente tentasse di autenticarsi

System.Web.SessionState.SessionStateModule , la proprietà s_sessionEverSet è vera. Gli ID sessione vengono generati da SessionStateModule , ASP.NET_SessionId viene aggiunto alla raccolta System.Web.HttpResponse.Cookies ma viene rimosso in seguito nella durata della richiesta poiché la sessione dell'utente è effettivamente vuota. In questo caso, lo stato della raccolta System.Web.HttpResponse.Cookies viene rilevato come modificato e l' intestazione Set-Cookie viene prima cancellata prima che i cookie vengano serializzati sul valore dell'intestazione.

In questo caso i cookie di risposta OWIN vengono "persi" e l'utente non viene autenticato e viene reindirizzato alla pagina di accesso.

Caso 3: la sessione viene utilizzata prima che l'utente tenti di autenticarsi

System.Web.SessionState.SessionStateModule , la proprietà s_sessionEverSet è vera. Gli ID sessione vengono generati da SessionStateModule , ASP.NET_SessionId viene aggiunto a System.Web.HttpResponse.Cookies . A causa dell'ottimizzazione interna in System.Web.HttpCookieCollection e System.Web.HttpResponse.GenerateResponseHeadersForCookies () L'intestazione Set-Cookie NON viene prima cancellata ma solo aggiornata.

In questo caso, sia i cookie di autenticazione OWIN che i cookie ASP.NET_SessionId vengono inviati in risposta e il login funziona.


Problema più generale con i cookie

Come puoi vedere, il problema è più generale e non limitato alla sessione ASP.NET. Se stai ospitando OWIN tramite Microsoft.Owin.Host.SystemWeb e tu / qualcosa stai usando direttamente la raccolta System.Web.HttpResponse.Cookies sei a rischio.

Ad esempio, funziona e entrambi i cookie vengono inviati correttamente al browser ...

public ActionResult Index()
{
    HttpContext.GetOwinContext()
        .Response.Cookies.Append("OwinCookie", "SomeValue");
    HttpContext.Response.Cookies["ASPCookie"].Value = "SomeValue";

    return View();
}

Ma non è così e OwinCookie è "perso" ...

public ActionResult Index()
{
    HttpContext.GetOwinContext()
        .Response.Cookies.Append("OwinCookie", "SomeValue");
    HttpContext.Response.Cookies["ASPCookie"].Value = "SomeValue";
    HttpContext.Response.Cookies.Remove("ASPCookie");

    return View();
}

Entrambi testati da VS2013, IISExpress e modello di progetto MVC predefinito.


7
Ho trascorso alcuni giorni cercando di eseguire il debug e risolvere questo problema nel nostro ambiente di test. L'unica soluzione che ho trovato è la stessa che hai suggerito (impostazione della sessione prima che l'utente esegua l'autenticazione). Ho segnalato il problema a katanaproject ... katanaproject.codeplex.com/workitem/197 , quindi forse qualcuno commenterà lì.
Tomas Dolezal,

11
Questo è un difetto piuttosto grave, soprattutto perché hanno confezionato il modello per vs2013.
Piotr Stulinski,

2
Per chiunque voglia indagare ulteriormente su questo, ho creato un progetto di test su github.com/Neilski/IdentityBugDemo
Neilski,

1
Incappare in questo problema a causa dell'uso di Controller.TempData che utilizza Session come archivio di backup. Può riprodurre prontamente l'impossibilità di accedere se un cookie ASP_NET.SessionId non esiste da una richiesta precedente.
Kingdango,

2
Finalmente! Che strano problema è questo. Grazie. Questo è ancora un problema oltre due anni dopo che questa risposta è stata scritta.
Spivonious

43

A partire dalla grande analisi di @TomasDolezal, ho dato un'occhiata sia alla fonte Owin che alla fonte System.Web.

Il problema è che System.Web ha una propria fonte principale di informazioni sui cookie e che non è l'intestazione Set-Cookie. Owin conosce solo l'intestazione Set-Cookie. Una soluzione alternativa è assicurarsi che anche tutti i cookie impostati da Owin siano impostati nella HttpContext.Current.Response.Cookiesraccolta.

Ho creato un piccolo middleware ( sorgente , nuget ) che fa esattamente questo, che deve essere posizionato immediatamente sopra la registrazione del middleware dei cookie.

app.UseKentorOwinCookieSaver();

app.UseCookieAuthentication(new CookieAuthenticationOptions());

1
Ci proverò. Dal momento che dopo asp.net Identity 2.2.0-alpha1 ho iniziato ad avere problemi non solo al login ma anche al logout dell'utente (l'utente non si disconnette al logout, fare clic su | in generale, nel caso in cui ho lasciato il sito aperto per qualche tempo senza fare nulla |) .. E dopo aver impostato una sessione appena prima che l'utente acceda abbia risolto il problema di accesso ma il problema di disconnessione persiste .. Grazie per il tuo sforzo .. A proposito, c'è qualcosa che dovrei fare tranne che per l'installazione di il pacchetto?
corteggia il

Devi attivarlo con app.UseKentorCookieMiddlewareSaver();in Startup.Auth.cs. Dovrebbe gestire anche la cancellazione dei cookie di logout.
Anders Abel,

Grazie mille Anders Abel, sia il login che il logout ora funzionano bene. Ma il codice nel commento sopra deve essere modificato (perché l'ho seguito :) senza successo) per essere: app.UseKentorOwinCookieSaver()e forse incluso nella tua risposta originale come nella pagina GitHub del pacchetto .
corteggia il

1
Grazie per aver notato il documento errato. In realtà è già stato corretto sulla pagina GitHub, ma ho aggiornato anche qui nella mia risposta.
Anders Abel,

@AndersAbel Sto cercando di aggiungere iscrizioni Meetup per questo progetto github: github.com/owin-middleware/OwinOAuthProviders ''. Ho aggiunto Asana solo l'altro giorno e non ho avuto problemi, ma per qualche motivo, con Meetup, l'attende il metodo AuthenticationManager.GetExternalLoginInfoAsync () in Account // ExternalLoginCallback sta restituendo null. Sfortunatamente, il tuo pacchetto NuGet non ha risolto il mio problema. Mi chiedevo se avessi del tempo per rivedere con me in quanto potresti essere in grado di risolvere meglio il problema e spingere verso il tuo progetto.
Anthony Ruffino,

42

In breve, il gestore dei cookie .NET conquisterà il gestore dei cookie OWIN e sovrascriverà i cookie impostati sul livello OWIN . La correzione consiste nell'utilizzare la classe SystemWebCookieManager, fornita come soluzione nel Progetto Katana qui . È necessario utilizzare questa classe o una simile, che costringerà OWIN a utilizzare il gestore dei cookie .NET, quindi non ci sono incoerenze :

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

All'avvio dell'applicazione, assegnalo quando crei le dipendenze OWIN:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    ...
    CookieManager = new SystemWebCookieManager()
    ...
});

Una risposta simile è stata fornita qui, ma non include tutto il codice necessario per risolvere il problema, quindi vedo la necessità di aggiungerlo qui perché il collegamento esterno al Progetto Katana potrebbe non funzionare e questo dovrebbe essere completamente riportato come soluzione anche qui.


grazie, mi funziona, ma anche azzerare tutte le sessioni chiamando questo ControllerContext.HttpContext.Session.RemoveAll (); in funzione externallogincallback
adnan,

Si applica ai moduli Web ASP.NET 4.6.1 ? La mia webApp utilizzaASP.NET Webforms, OWIN, ADFS
Kiquenet il

@Kiquenet La tua app Web utilizza i cookie OWIN? Allora si.
Alexandru,

Nel codice Startup.ConfigureAuthche abbiamo app.UseCookieAuthenticatione app.UseWsFederationAuthenticationinfine app.UseStageMarker
Kiquenet

@Alexandru Potresti prendere in considerazione una modifica, il mio team ha colpito questo bug ed era raro e casuale, nascosto da noi attraverso ambienti DEV e UAT. Questa citazione dalla tua risposta non ci è valsa la pena: "Il gestore di cookie .NET vincerà sempre". Sarebbe facile da trovare e correggere, se i cookie OWIN venissero sempre sovrascritti, nessuno dei nostri middleware OIDC sarebbe uscito dalle nostre workstation di sviluppo. Ma la casualità significava che il bug arrivava fino alla produzione per 2 giorni prima che ci colpisse su larga scala (metà dei nostri usi interni non potevano accedere tramite AAD). Ti dispiace se rimuovo la parola "sempre" dalla tua risposta?
yzorg,

17

Il team di Katana ha risposto al problema sollevato da Tomas Dolezar e ha pubblicato la documentazione relativa alle soluzioni alternative :

Le soluzioni alternative rientrano in due categorie. Uno è quello di riconfigurare System.Web in modo da evitare l'utilizzo della raccolta Response.Cookies e la sovrascrittura dei cookie OWIN. L'altro approccio consiste nel riconfigurare i componenti OWIN interessati in modo che scrivano i cookie direttamente nella raccolta Response.Cookies di System.Web.

  • Assicurarsi che la sessione sia stabilita prima dell'autenticazione: il conflitto tra i cookie System.Web e Katana è per richiesta, quindi potrebbe essere possibile che l'applicazione stabilisca la sessione su una richiesta prima del flusso di autenticazione. Questo dovrebbe essere facile da fare quando arriva l'utente per la prima volta, ma potrebbe essere più difficile garantire in seguito quando i cookie di sessione o di autenticazione scadono e / o devono essere aggiornati.
  • Disabilita il SessionStateModule: se l'applicazione non si basa sulle informazioni sulla sessione, ma il modulo di sessione sta ancora impostando un cookie che causa il conflitto di cui sopra, è possibile disabilitare il modulo di stato della sessione.
  • Riconfigurare CookieAuthenticationMiddleware per scrivere direttamente nella raccolta di cookie di System.Web.
app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

Vedi l'implementazione di SystemWebCookieManager dalla documentazione (link sopra)

Maggiori informazioni qui

modificare

Di seguito i passaggi che abbiamo preso per risolvere il problema. Sia 1. che 2. hanno risolto il problema anche separatamente, ma abbiamo deciso di applicare entrambi nel caso in cui:

1. Usa SystemWebCookieManager

2. Impostare la variabile di sessione:

protected override void Initialize(RequestContext requestContext)
{
    base.Initialize(requestContext);

    // See http://stackoverflow.com/questions/20737578/asp-net-sessionid-owin-cookies-do-not-send-to-browser/
    requestContext.HttpContext.Session["FixEternalRedirectLoop"] = 1;
}

(nota a margine: il metodo Initialize sopra è il posto logico per la correzione perché base.Initialize rende disponibile Session. Tuttavia, la correzione potrebbe essere applicata anche in seguito perché in OpenId c'è prima una richiesta anonima, quindi reindirizza al provider OpenId e poi indietro all'app. I problemi si verificherebbero dopo il reindirizzamento all'app, mentre la correzione imposta la variabile di sessione già durante la prima richiesta anonima, risolvendo così il problema anche prima che si verifichi un eventuale reindirizzamento)

Modifica 2

Copia e incolla dal progetto Katana 14/05/2016:

Aggiungi questo:

app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

...e questo:

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

Trovo che questa risposta sia molto più semplice e facile da risolvere. Grazie, forse ho parlato troppo all'improvviso. Questo non ha risolto il mio problema.
JCS

@JCS Incluso i passaggi che abbiamo intrapreso per risolvere il problema. Hai scoperto se il tuo problema era correlato?
thomius il

Sto usando Web Api 2 + middleware Owin + cache redis per la gestione delle sessioni per l'autenticazione. Ho provato a utilizzare SystemWebCookieManager e non ha risolto il problema che avevo riscontrato in cui non venivano impostati i cookie di autenticazione. L'uso di "UseKentorOwinCookieSaver" ha risolto il problema, ma non sono troppo affezionato a una dipendenza esterna aggiuntiva ...
JCS,

Cancellare la sessione ha funzionato per me. Nessuna dipendenza esterna necessaria. Metti questo ControllerContext.HttpContext.Session.RemoveAll();nella tua ExternalLogin()azione, prima di chiamare ChallengeResult(). Non so se sia la soluzione migliore, ma è la più semplice.
Alisson,

1
@chemitaxè certo, prendi nota che l' ?.operatore (null-conditional) funziona solo in C # 6.
Alisson,

5

Le risposte sono già state fornite, ma in owin 3.1.0 esiste una classe SystemWebChunkingCookieManager che può essere utilizzata.

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

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    ...
    CookieManager = new SystemWebChunkingCookieManager()
    ...
});

È ancora un problema in 3.1.0?
Cyberconte,

1
Sì, è ancora un problema in 3.1.0 per me e avevo bisogno di questo gestore di cookie, poiché quello predefinito è ancora ChunkingCookieManager.
jonmeyer,

può essere usato dove? e come?
Simon_Weaver il

@jonmeyer grazie. Penso che ieri ho perso la distinzione tra SystemCCM e CCM, quindi lo verificherò sicuramente
Simon_Weaver,

anche dopo aver aggiunto la riga sopra non funziona per me. sto usando la versione 3.1.0. Principalmente sono in grado di accedere per la prima volta ma dopo il logout non mi consente di accedere.
Mitin Dixit,

3

Se stai impostando i cookie nel middleware OWIN da solo, allora l'utilizzo OnSendingHeaderssembra aggirare il problema.

Ad esempio, owinResponseCookie2verrà impostato l'utilizzo del codice seguente , anche se owinResponseCookie1non lo è:

private void SetCookies()
{
    var owinContext = HttpContext.GetOwinContext();
    var owinResponse = owinContext.Response;

    owinResponse.Cookies.Append("owinResponseCookie1", "value1");

    owinResponse.OnSendingHeaders(state =>
    {
        owinResponse.Cookies.Append("owinResponseCookie2", "value2");
    },
    null);

    var httpResponse = HttpContext.Response;
    httpResponse.Cookies.Remove("httpResponseCookie1");
}

3

Ho affrontato il problema simile con Visual Studio 2017 e .net MVC 5.2.4 , aggiornando Nuget Microsoft.Owin.Security.Google alla versione più recente che attualmente è 4.0.1 ha funzionato per me! Spero che questo aiuti qualcuno!


1
Ho salvato la mia pancetta su questo! Stavo riscontrando un problema con Android Chrome specificatamente perdendo l'autenticazione a caso. Nient'altro in questo thread ha funzionato. Sto usando VS2019 e ASP MVC 5.
zfrank

2

La soluzione di codice a una riga più veloce:

HttpContext.Current.Session["RunSession"] = "1";

Aggiungi questa riga prima del metodo CreateIdentity:

HttpContext.Current.Session["RunSession"] = "1";
var userIdentity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
_authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberLogin }, userIdentity);

1
Dove hai inserito questo codice HttpContext.Current.Session["RunSession"] = "1";? in Globa.asax Session_Start ?
Kiquenet,

1
È in effetti la soluzione più semplice e veloce disponibile, e fino a quando la soluzione di quel problema non sarà inclusa nel Framework (già annunciato che lo farà) - Io, per esempio, preferirei una linea, invece di una classe + un mucchio di dipendenze . Questa soluzione è sottovalutata da IMHO.
Der Zinger,

L'ho aggiunto nel mio AuthManager nella parte superiore del metodo IssueAuthToken
Alexander Trofimov,

1

Ho avuto lo stesso sintomo dell'intestazione Set-Cookie non inviata, ma nessuna di queste risposte mi ha aiutato. Tutto ha funzionato sul mio computer locale ma, quando distribuito alla produzione, le intestazioni del set-cookie non sarebbero mai state impostate.

Si è scoperto che era una combinazione di utilizzo di un custom CookieAuthenticationMiddlewarecon WebApi insieme al supporto di compressione WebApi

Fortunatamente stavo usando ELMAH nel mio progetto che mi ha permesso di registrare questa eccezione:

System.Web.HttpException Server non può aggiungere l'intestazione dopo che le intestazioni HTTP sono state inviate.

Il che mi ha portato a questo problema GitHub

Fondamentalmente, se hai una configurazione strana come la mia, vorrai disabilitare la compressione per i tuoi controller / metodi WebApi che impostano i cookie o provare il OwinServerCompressionHandler.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.