考虑以下情况:
<sessionState cookieless="AutoDetect" />
的.NET应用程序。HttpWebRequest
(无cookie)向其发送数据。这个看似简单的案例导致重大失败。
由于.NET无法确定请求代理(HttpWebRequest
)是否支持cookie,因此它会响应POST请求,并将302 Found重定向到同一位置:
AspxAutoDetectCookie
的Cookie AspxAutoDetectCookie
的查询参数然后请求代理请求新位置HttpWebRequest
。当.NET在查询字符串中看到AspxAutoDetectCookie
时,它知道这是一个重新请求,它可以通过查看名为AspxAutoDetectCookie
的cookie是否在请求标头中来确定是否支持cookie。
问题是,大多数请求代理(Web浏览器,HttpWebRequest
)将302 Found视为303 See Other,并将重新请求设为GET,而不管原始HTTP方法如何!在初始POST请求中发送的任何数据都不会被转发。
正确的响应应该是307临时重定向,它不会更改请求方法。 (对位置X的POST请求重定向到 POST 请求到位置Y.)
有没有办法在.NET中更改此行为,因此POST请求不会被销毁?
答案 0 :(得分:2)
我能看到的唯一解决方案是将AspxAutoDetectCookie=1
附加到所有POST请求。
这样,ASP.NET永远不会重定向请求,我们可以完全避开302 vs 307问题。如果cookie被嵌入到请求中,ASP.NET将检测到支持cookie,如果没有嵌入cookie,它将假定它们不是。
答案 1 :(得分:0)
使用cookieless =“UseDeviceProfile”有什么问题吗?您可以将其用作解决方案。
答案 2 :(得分:0)
如果cookiless = true,您也会看到问题。你真的帮帮我了我甚至无法弄清楚是什么导致了这个问题,直到我从web.config中删除了行设置sessionstate cookilesss为true,看到问题已解决,google了我的搜索结果并找到了此页面。您帮助解释了为什么删除此行可以解决问题。如果您找到的解决方案不涉及更改我使用会话状态的方式,您能告诉我吗?
答案 3 :(得分: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()
{}
}
}