设置 <sessionState cookieless="AutoDetect" /> 时 POST 请求失败
Posted
技术标签:
【中文标题】设置 <sessionState cookieless="AutoDetect" /> 时 POST 请求失败【英文标题】:POST requests fail when <sessionState cookieless="AutoDetect" /> is set 【发布时间】:2011-04-01 05:52:30 【问题描述】:考虑以下情况:
Web 服务器正在运行带有<sessionState cookieless="AutoDetect" />
的 .NET 应用程序。
客户端使用简单的HttpWebRequest
(无 cookie)向其发布数据。
这个看似简单的案例却导致重大失败。
由于 .NET 无法确定请求代理 (HttpWebRequest
) 是否支持 cookie,它使用 302 Found 重定向到相同位置来响应 POST 请求:
AspxAutoDetectCookie
的 cookie
转发位置中名为AspxAutoDetectCookie
的查询参数
然后请求代理应该请求新位置,HttpWebRequest
会这样做。当 .NET 在查询字符串中看到 AspxAutoDetectCookie
时,它就知道这是一个重新请求,它可以通过查看名为 AspxAutoDetectCookie
的 cookie 是否在请求标头中来确定是否支持 cookie。
问题在于大多数请求代理(Web 浏览器,HttpWebRequest
)将 302 Found 视为 303 See Other 并将重新请求设为 GET,而不管原始 HTTP 方法如何!初始 POST 请求中发送的任何数据都不会被转发。
正确的响应应该是307 Temporary Redirect,不会改变请求方式。 (对位置 X 的 POST 请求会重定向到对位置 Y 的 POST 请求。)
有什么方法可以改变 .NET 中的这种行为,使 POST 请求不会被破坏?
Information on 3xx redirection
【问题讨论】:
【参考方案1】:我知道线程很旧,但是另一个可行的解决方案是创建 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()
【讨论】:
【参考方案2】:我能看到的唯一解决方案是将AspxAutoDetectCookie=1
附加到所有 POST 请求。
这样,ASP.NET 将永远不会重定向请求,我们可以完全避开 302 与 307 的问题。如果请求中嵌入了 cookie,ASP.NET 将检测到支持 cookie,如果没有嵌入 cookie,则假定它们不支持。
【讨论】:
如果我们附加标题就可以了:Cookie:AspxAutoDetectCookie=1
.【参考方案3】:
使用 cookieless="UseDeviceProfile" 有什么问题吗?您可以将其用作解决方法。
【讨论】:
很遗憾,我无法使用该设置。它必须与“自动检测”一起使用。以上是关于设置 <sessionState cookieless="AutoDetect" /> 时 POST 请求失败的主要内容,如果未能解决你的问题,请参考以下文章
web。config中如何修改sessionstate 模式设置
在C#中,在Web.Config文件中加入<sessionState mode="InProc"></sessionState>语句