7

考虑以下情况:

  • Web 服务器正在运行带有 .NET 的 .NET 应用程序<sessionState cookieless="AutoDetect" />
  • HttpWebRequest客户端使用简单的(无 cookie)向其发布数据。

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

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

  • AspxAutoDetectCookie响应中命名的 cookie
  • AspxAutoDetectCookie在转发位置命名的查询参数

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

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

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

有什么方法可以改变.NET 中的这种行为,所以 POST 请求不会被破坏?

3xx 重定向信息

4

3 回答 3

2

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

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

于 2010-08-24T22:09:10.247 回答
0

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

于 2010-08-20T07:35:25.913 回答
0

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

这是我使用的一个

            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()
                {}
              }
            }
于 2015-10-29T14:54:43.390 回答