Domanda

Si consideri il seguente caso:

  • Un server Web è in esecuzione un'applicazione .NET con <sessionState cookieless="AutoDetect" />.
  • Un client è un dato annuncio a esso con un HttpWebRequest semplice (nessun cookie).

Questa apparentemente semplice caso provoca grande fallimento.

Dato .NET non può determinare se l'agente richiedente (HttpWebRequest) supporta i cookie, si risponde alla richiesta POST con un reindirizzamento Trovato 302 nella stessa posizione con:

  • un cookie di nome AspxAutoDetectCookie nella risposta
  • un AspxAutoDetectCookie parametro di query denominata in posizione inoltrato

L'agente richiedente è quindi dovuto chiedere la nuova posizione, che HttpWebRequest fa. Quando .NET vede AspxAutoDetectCookie nella stringa di query, si sa che questo è un re-richiesta, ed è in grado di determinare se i cookie sono supportati da vedere se un cookie di nome AspxAutoDetectCookie è nelle intestazioni di richiesta.

Il problema è che la maggior parte agenti richiedente (browser web, HttpWebRequest) trattare una 302 Found come se si tratta di un 303 Vedi gli altri e fare la ri-richiesta di un GET, indipendentemente dal metodo HTTP originale! Tutti i dati inviati nella richiesta POST iniziale non viene inoltrato.

La risposta corretta dovrebbe essere una temporanea reindirizzamento 307, che non cambia il metodo di richiesta. (Richiesta di un post per redirect posizione X a una su POST richiesta posizione Y).

C'è un modo per cambiare questo comportamento in .NET in modo richieste POST non vengono distrutti?

Informazioni sul 3xx reindirizzamento

È stato utile?

Soluzione

L'unica soluzione che posso vedere a questo è di aggiungere AspxAutoDetectCookie=1 a tutte le richieste POST.

In questo modo, ASP.NET non potrà mai reindirizzare la richiesta e noi possiamo schivare la questione 302 vs 307 del tutto. Se i cookie sono incorporati nella richiesta, ASP.NET rileva che i cookie sono supportati, e se nessun cookie sono incorporati, si assumerà che non sono.

Altri suggerimenti

Ci sono problemi nell'uso cookieless = "UseDeviceProfile"? Potete usarlo come una soluzione alternativa.

Si vede anche il problema se cookiless = true. Mi hai davvero aiutato. Non riuscivo nemmeno a capire che cosa stava causando questo problema fino a quando ho tolto l'impostazione cookilesss sessionstate true dal mio web.config linea, visto il problema risolto, su Google i miei risultati e ho trovato questa pagina. Hai aiutato a spiegare perché la rimozione di questa linea ha risolto il problema. Può farmi sapere se si trova una soluzione che non comporta la modifica il modo in cui io uso lo stato della sessione?

So che il filo è vecchio ma, un'altra soluzione praticabile è quella di creare e HTTP Modulo di correzione HTTP Post cookie sopra.

Ecco un uso i

            using System;
            using System.Collections.Specialized;
            using System.Web;
            using System.Web.SessionState;
            using System.IO;
            using System.Text;

            namespace CustomModule
            {
              public sealed class CookielessPostFixModule : IHttpModule
              {
                public void Init (HttpApplication application)
                {
                  application.EndRequest += new
                              EventHandler(this.Application_EndRequest);
                }
                private string ConstructPostRedirection(HttpRequest req,
                                                        HttpResponse res)
                {
                  StringBuilder build = new StringBuilder();
                  build.Append(
              "<html>\n<body>\n<form name='Redirect' method='post' action='");
                  build.Append(res.ApplyAppPathModifier(req.Url.PathAndQuery));
                  build.Append("' id='Redirect' >");
                  foreach (object obj in req.Form)
                  {
                    build.Append(string.Format(
              "\n<input type='hidden' name='{0}' value = '{1}'>",
                      (string)obj,req.Form[(string)obj]));
                  }
                  build.Append(
              "\n<noscript><h2>Object moved <input type='submit' value='here'></h2></noscript>");
                  build.Append(@"</form>"+
                  "<script language='javascript'>"+
                  "<!--"+
                  "document.Redirect.submit();"+
                  "// -->"+
                  "</script>");
                  build.Append("</body></html>");
                  return build.ToString();
                }
                private bool IsSessionAcquired
                {
                  get
                  {
                    return (HttpContext.Current.Items["AspCookielessSession"]!=null && 
                    HttpContext.Current.Items["AspCookielessSession"].ToString().Length>0);
                  }
                }
                private string ConstructPathAndQuery(string[] segments)
                {
                  StringBuilder build = new StringBuilder(); 

                  for (int i=0;i<segments.Length;i++)
                  {
                    if (!segments[i].StartsWith("(") 
                             && !segments[i].EndsWith(")"))
                      build.Append(segments[i]);
                  }
                  return build.ToString();
                }
                private bool IsCallingSelf(Uri referer,Uri newpage)
                {
                  if(referer==null || newpage==null)
                    return false;
                  string refpathandquery = ConstructPathAndQuery(
                                                    referer.Segments);
                  return refpathandquery == newpage.PathAndQuery;
                }
                private bool ShouldRedirect
                {
                  get
                  {
                    HttpRequest req = HttpContext.Current.Request;

                    return (!IsSessionAcquired
                                && req.RequestType.ToUpper() == "POST"
                      && !IsCallingSelf(req.UrlReferrer,req.Url));
                  }
                }
                private void Application_EndRequest(Object source, EventArgs e)
                {
                  HttpRequest req = HttpContext.Current.Request;
                  HttpResponse res = HttpContext.Current.Response;
                  if (!ShouldRedirect) return;
                  res.ClearContent();
                  res.ClearHeaders();
                  res.Output.Flush();
                  char[] chr = ConstructPostRedirection(req,res).ToCharArray();
                  res.Write(chr,0,chr.Length);
                }
                public void Dispose()
                {}
              }
            }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top