7

Рассмотрим следующий случай:запросы POST терпят неудачу, когда <sessionState Cookieless = "AutoDetect" /> установлено

  • Веб-сервер работает приложение .NET с <sessionState cookieless="AutoDetect" />.
  • Клиент отправляет данные на него с помощью простого HttpWebRequest (без файлов cookie).

Этот, казалось бы, простой случай вызывает серьезный сбой.

Поскольку .NET не может определить, является ли запрашивающий агент (HttpWebRequest) поддерживает куки, он отвечает на запрос POST с 302 Найдено перенаправлением на то же место с:

  • печенья под названием AspxAutoDetectCookie в ответ
  • параметр запроса с именем AspxAutoDetectCookie в пересылаемом месте

запрашивающая агент затем должен запросить новое место, которое HttpWebRequest делает. Когда .NET видит AspxAutoDetectCookie в строке запроса, он знает, что это повторный запрос, и он может определить, поддерживаются ли файлы cookie, если в заголовках запроса находится файл cookie с именем AspxAutoDetectCookie.

Проблема заключается в том, что большинство запрашивающих агентов (веб-браузеры, HttpWebRequest) относятся к 302 найденному, как если бы это 303 См. Раздел «Другое» и перепродайте GET, независимо от исходного метода HTTP! Любые данные, отправленные в исходном запросе POST, не пересылаются.

Правильный ответ должен быть временным перенаправлением 307, который не меняет метод запроса. (Запрос POST в адрес X перенаправляется на адрес POST запрос на адрес Y.)

Есть ли способ изменить это поведение в .NET, поэтому запросы POST не будут уничтожены?

Information on 3xx redirection

ответ

1

Единственное решение, которое я вижу, - добавить AspxAutoDetectCookie=1 ко всем запросам POST.

Таким образом, ASP.NET никогда не перенаправит запрос, и мы можем уклониться от вопроса 302 против 307. Если в запросе встроены файлы cookie, ASP.NET обнаружит, что куки-файлы поддерживаются, и если куки не внедрены, предполагается, что они не являются.

+0

Не работает здесь, по крайней мере. Все еще сбрасывает данные сообщения. – Karlth

+0

Он работает, если мы добавляем заголовок: 'Cookie: AspxAutoDetectCookie = 1'. – Artyom

0

Существуют ли какие-либо проблемы при использовании Cookieless = "UseDeviceProfile"? Вы можете использовать его в качестве обходного решения.

+0

К сожалению, я не могу использовать эту установку. Он должен работать с «AutoDetect». – Anton

0

Вы также видите проблему, если cookiless = true. Ты действительно помог мне. Я даже не мог понять, что вызвало эту проблему, пока я не удалил строку, устанавливающую cookieesss sessionstate, на true из моего web.config, увидел, что проблема исправлена, googled мои результаты и нашел эту страницу. Вы помогли объяснить, почему удаление этой строки устраняет проблему. Можете ли вы сообщить мне, если вы найдете решение, которое не связано с изменением способа использования состояния сеанса?

0

Я знаю, что тема старая, но еще одно жизнеспособное решение - создать и HTTP-модуль, чтобы исправить HTTP-сообщение поверх 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() 
       {} 
       } 
      }