POST-Anforderungen fehlschlagen, wenn Set ist
-
29-09-2019 - |
Frage
Betrachten Sie den folgenden Fall:
- Ein Web-Server eine .NET-Anwendung mit
<sessionState cookieless="AutoDetect" />
ausgeführt wird. - Ein Client ist POSTen Daten, die ihm ein einfaches
HttpWebRequest
mit (keine Cookies).
Dieser scheinbar einfache Fall verursacht schwerwiegenden Fehler.
Da .NET kann nicht feststellen, ob der anfragende Agent (HttpWebRequest
) unterstützt Cookies, es auf die Anforderung POST antwortet mit einer 302 gefunden Umleitung auf die gleiche Stelle mit:
- ein Cookie namens
AspxAutoDetectCookie
in der Antwort - eine Abfrage Parameter namens
AspxAutoDetectCookie
in der weitergeleiteten Lage
Der anfragende Agent soll dann die neue Position beantragen, die HttpWebRequest
tut. Wenn .NET AspxAutoDetectCookie
in dem Query-String sieht, es weiß dies eine erneute Anforderung ist, und es kann bestimmen, ob Cookies durch Sehen unterstützt werden, wenn ein Cookie namens AspxAutoDetectCookie
ist in den Request-Header.
Das Problem ist, dass die meisten anfordernden Agenten (Web-Browser, HttpWebRequest
) behandeln, um eine 302 gefunden, als ob es sich um ein 303 See Other ist und die Wieder Anforderung eine GET machen, unabhängig von der ursprünglichen HTTP-Methode! Alle Daten in der Anfangs POST-Anforderung gesendet wird nicht weitergeleitet.
Die richtige Antwort sollte ein 307 Temporary Redirect sein, die nicht die Request-Methode ändert. (A POST-Anforderung an Stelle X Umleitungen zu einer POST Anfrage an Position Y.)
Gibt es eine Möglichkeit, dieses Verhalten in .NET zu ändern, so POST-Anfragen nicht zerstört werden?
Lösung
Die einzige Lösung, die ich auf diese sehen kann, ist AspxAutoDetectCookie=1
an alle POST-Anfragen anzuhängen.
Auf diese Weise ASP.NET wird nie die Anfrage umleiten und wir können die 302 vs 307 Frage gänzlich ausweichen. Wenn Cookies im Request eingebettet sind, wird ASP.NET erkennen, dass Cookies unterstützt werden, und wenn keine Cookies eingebettet sind, werden sie annehmen, dass sie nicht sind.
Andere Tipps
Gibt es Probleme in cookieless mit = "UseDeviceProfile"? Sie können es als eine Umgehungslösung verwenden.
Sie sehen auch die Frage, ob cookiless = true. Sie half mir wirklich heraus. Ich konnte nicht einmal herausfinden, was das Problem verursacht wurde, bis ich die Linie Einstellung session cookilesss auf true von meinem web.config entfernt, sah das Problem behoben, googeln meine Ergebnisse und diese Seite gefunden. Sie half erklären, warum diese Zeile entfernt das Problem behoben. Können Sie es mich wissen lassen, wenn Sie eine Lösung finden, die nicht die Art, wie ich Sitzungszustand ändert sich bringt verwenden?
Ich weiß, dass der Faden alt ist, aber eine andere praktikable Lösung ist die Schaffung und HTTP-Modul fix http Post über cookieless.
Hier ist eine i Verwendung
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()
{}
}
}