7

folgenden Fall vor:POST-Anfragen fehlschlagen, wenn <session cookieless = "AutoDetect" /> gesetzt

  • Ein Webserver eine .NET-Anwendung mit <sessionState cookieless="AutoDetect" /> läuft.
  • Ein Client sendet Daten an ihn mit einem einfachen HttpWebRequest (keine Cookies).

Dieser scheinbar einfache Fall verursacht einen großen Fehler.

Da .NET kann nicht feststellen, ob der anfragende Agent (HttpWebRequest) Cookies unterstützt, antwortet er auf die POST-Anforderung mit einer 302 gefunden Umleitung auf die gleiche Stelle mit:

  • ein Cookie AspxAutoDetectCookie in dem genannten Antwort
  • ein Abfrageparameter, soll die neue Stelle beantragen, die HttpWebRequest tut AspxAutoDetectCookie in der weitergeleiteten Lage

der anfragende Agent dann gestattet. Wenn .NET AspxAutoDetectCookie in der Abfragezeichenfolge sieht, weiß es, dass es sich um eine erneute Anforderung handelt, und kann ermitteln, ob Cookies unterstützt werden, indem festgestellt wird, ob sich ein Cookie mit dem Namen AspxAutoDetectCookie in den Anforderungsheadern befindet.

Das Problem ist, dass die meisten anfragenden Agenten (Webbrowser, HttpWebRequest) behandeln eine 302 gefunden, als ob es ein 303 Siehe Andere und machen Sie die erneute Anforderung eines GET, unabhängig von der ursprünglichen HTTP-Methode! Alle in der anfänglichen POST-Anfrage gesendeten Daten werden nicht weitergeleitet.

Die richtige Antwort sollte eine 307 Temporary Redirect sein, die die Request-Methode nicht ändert. (A POST-Anforderung an Position X leitet zu einer POST Anfrage Standort Y.)

Gibt es eine Möglichkeit, dieses Verhalten in .NET zu ändern, so POST-Anfragen nicht zerstört werden?

Information on 3xx redirection

Antwort

1

Die einzige Lösung, die ich sehen kann, ist, an alle POST-Anfragen AspxAutoDetectCookie=1 anhängen.

Auf diese Weise wird ASP.NET nie die Anfrage umleiten und wir können die 302 vs 307 Frage insgesamt ausweichen. Wenn Cookies in die Anfrage eingebettet werden, erkennt ASP.NET, dass Cookies unterstützt werden, und wenn keine Cookies eingebettet sind, wird davon ausgegangen, dass dies nicht der Fall ist.

+0

Funktioniert hier zumindest nicht. Lässt immer noch die Postdaten fallen. – Karlth

+0

Es funktioniert, wenn wir den Header anhängen: 'Cookie: AspxAutoDetectCookie = 1'. – Artyom

0

Gibt es Probleme bei der Verwendung cookieless = "UseDeviceProfile"? Sie können es als eine Umgehungslösung verwenden.

+0

Leider kann ich diese Einstellung nicht verwenden. Es muss mit "AutoDetect" funktionieren. – Anton

0

Sie sehen auch das Problem, wenn cookiless = true. Du hast mir wirklich geholfen. Ich konnte nicht einmal herausfinden, was dieses Problem verursachte, bis ich die Zeile, die den Sitzungsstatus cookiless auf true gesetzt hatte, aus meiner web.config entfernte, das Problem erkannte, meine Ergebnisse googelte und diese Seite fand. Sie haben erklärt, warum das Entfernen dieser Zeile das Problem behoben hat. Können Sie mich wissen lassen, wenn Sie eine Lösung finden, die die Art, wie ich den Sitzungsstatus verwende, nicht ändert?

0

Ich weiß, der Thread ist alt, aber eine andere praktikable Lösung ist zu erstellen und HTTP-Modul zu http Post über cookieless zu beheben.

Hier ist ein i verwenden

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