设置时,POST请求失败

时间:2022-12-26 20:20:40

Consider the following case:

考虑以下情况:

  • A web server is running a .NET app with <sessionState cookieless="AutoDetect" />.
  • Web服务器正在运行带有 的.NET应用程序。

  • A client is POSTing data to it using a simple HttpWebRequest (no cookies).
  • 客户端使用简单的HttpWebRequest(无cookie)向其发送数据。

This seemingly simple case causes major failure.

这个看似简单的案例导致重大失败。

Since .NET can't determine if the requesting agent (HttpWebRequest) supports cookies, it responds to the POST request with a 302 Found redirect to the same location with:

由于.NET无法确定请求代理(HttpWebRequest)是否支持cookie,因此它会响应POST请求,并将302 Found重定向到同一位置:

  • a cookie named AspxAutoDetectCookie in the response
  • 响应中名为AspxAutoDetectCookie的cookie

  • a query parameter named AspxAutoDetectCookie in the forwarded location
  • 转发位置中名为AspxAutoDetectCookie的查询参数

The requesting agent is then supposed to request the new location, which HttpWebRequest does. When .NET sees AspxAutoDetectCookie in the query string, it knows this is a re-request, and it can determine if cookies are supported by seeing if a cookie named AspxAutoDetectCookie is in the request headers.

然后,请求代理程序应该请求HttpWebRequest执行的新位置。当.NET在查询字符串中看到AspxAutoDetectCookie时,它知道这是一个重新请求,它可以通过查看名为AspxAutoDetectCookie的cookie是否在请求标头中来确定是否支持cookie。

The problem is that most requesting agents (web browsers, HttpWebRequest) treat a 302 Found as if it is a 303 See Other and make the re-request a GET, regardless of the original HTTP method! Any data sent in the initial POST request is not forwarded.

问题是,大多数请求代理(Web浏览器,HttpWebRequest)将302 Found视为303 See Other并将重新请求设置为GET,而不管原始HTTP方法如何!在初始POST请求中发送的任何数据都不会被转发。

The correct response should be a 307 Temporary Redirect, which does not change the request method. (A POST request to location X redirects to a POST request to location Y.)

正确的响应应该是307临时重定向,它不会更改请求方法。 (对位置X的POST请求重定向到位置Y的POST请求。)

Is there any way to change this behaviour in .NET so POST requests are not destroyed?

有没有办法在.NET中更改此行为,因此POST请求不会被销毁?

Information on 3xx redirection

有关3xx重定向的信息

4 个解决方案

#1


1  

The only solution I can see to this is to append AspxAutoDetectCookie=1 to all POST requests.

我能看到的唯一解决方案是将AspxAutoDetectCookie = 1附加到所有POST请求。

This way, ASP.NET will never redirect the request and we can dodge the 302 vs 307 question altogether. If cookies are embedded in the request, ASP.NET will detect that cookies are supported, and if no cookies are embedded, it will assume they aren't.

这样,ASP.NET将永远不会重定向请求,我们可以完全避开302 vs 307问题。如果cookie被嵌入到请求中,ASP.NET将检测到支持cookie,如果没有嵌入cookie,它将假定它们不是。

#2


0  

Are there any issues in using cookieless="UseDeviceProfile"? You may use it as a workaround solution.

使用cookieless =“UseDeviceProfile”有什么问题吗?您可以将其用作解决方案。

#3


0  

You also see the issue if cookiless=true. You really helped me out. I couldn't even figure out what was causing this issue until I removed the line setting sessionstate cookilesss to true from my web.config, saw the problem fixed, googled my results and found this page. You helped explain why removing this line fixed the problem. Can you let me know if you find a solution that doesn't involve changing the way I use session state?

如果cookiless = true,您还会看到问题。你真的帮帮我了我甚至无法弄清楚是什么导致了这个问题,直到我从web.config中删除了行设置sessionstate cookilesss为true,看到问题已解决,google了我的搜索结果并找到了此页面。您帮助解释了为什么删除此行可以解决问题。如果您找到的解决方案不涉及更改我使用会话状态的方式,您能告诉我吗?

#4


0  

I Know the thread is old but, another viable solution is to create and HTTP Module to fix http post over cookieless.

我知道线程已经老了但是,另一个可行的解决方案是创建和HTTP模块来修复http post over cookieless。

Here is one i use

这是我用的一个

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

#1


1  

The only solution I can see to this is to append AspxAutoDetectCookie=1 to all POST requests.

我能看到的唯一解决方案是将AspxAutoDetectCookie = 1附加到所有POST请求。

This way, ASP.NET will never redirect the request and we can dodge the 302 vs 307 question altogether. If cookies are embedded in the request, ASP.NET will detect that cookies are supported, and if no cookies are embedded, it will assume they aren't.

这样,ASP.NET将永远不会重定向请求,我们可以完全避开302 vs 307问题。如果cookie被嵌入到请求中,ASP.NET将检测到支持cookie,如果没有嵌入cookie,它将假定它们不是。

#2


0  

Are there any issues in using cookieless="UseDeviceProfile"? You may use it as a workaround solution.

使用cookieless =“UseDeviceProfile”有什么问题吗?您可以将其用作解决方案。

#3


0  

You also see the issue if cookiless=true. You really helped me out. I couldn't even figure out what was causing this issue until I removed the line setting sessionstate cookilesss to true from my web.config, saw the problem fixed, googled my results and found this page. You helped explain why removing this line fixed the problem. Can you let me know if you find a solution that doesn't involve changing the way I use session state?

如果cookiless = true,您还会看到问题。你真的帮帮我了我甚至无法弄清楚是什么导致了这个问题,直到我从web.config中删除了行设置sessionstate cookilesss为true,看到问题已解决,google了我的搜索结果并找到了此页面。您帮助解释了为什么删除此行可以解决问题。如果您找到的解决方案不涉及更改我使用会话状态的方式,您能告诉我吗?

#4


0  

I Know the thread is old but, another viable solution is to create and HTTP Module to fix http post over cookieless.

我知道线程已经老了但是,另一个可行的解决方案是创建和HTTP模块来修复http post over cookieless。

Here is one i use

这是我用的一个

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