【问题标题】:Cookieless sessions and cross-site form posts无 Cookie 会话和跨站点表单帖子
【发布时间】:2011-01-01 08:37:59
【问题描述】:

情况是这样的……

站点 1) 供客户登录、查看和支付账单等的 ASP.NET MVC 应用程序。该站点使用无 cookie 的 ASP 会话来允许多个会话在选项卡式浏览器中运行。

站点 2) 具有标准静态内容的企业网站。这将在每个页面的顶部有一个小表单,其中包含一个用户名/密码表单,该表单将发布到 MVC 应用程序。

当发布到 MVC 应用程序时,正在生成一个新会话,并且该站点正在返回一个 302 重定向,其中包含 URL 中的会话 ID(如预期的那样)。控制器有两种登录方法,一种用于处理 GET,一种用于处理 POST。由于重定向,它正在使用 GET 方法并丢失表单值。

通过将公司网站上的方法更改为执行表单 GET 而不是 POST,用户名和密码在重定向后保留在查询字符串中,我可以通过这种方式处理请求,但我宁愿执行 POST而不是在 URL 中传递该数据。

我的直觉告诉我,实现某种自定义 HttpHandler 可以让我做到这一点,但我不确定在哪里可以与会话创建相关联。 global.asax 中 Session_Start 处的断点表明会话 ID 已被创建,并且重定向已在该点发生。

【问题讨论】:

    标签: asp.net-mvc cookies


    【解决方案1】:

    我相信我找到了重定向发生的位置以及可能的解决方案。 ISessionIDManager 接口有一个带有“out bool redirected”参数的 SaveSessionID 方法。似乎在创建新会话时,默认会话管理器会重写此方法内的 URL 并进行重定向。我尝试实现自己的 ISessionIDManager 并且能够抑制重定向,但是没有办法(我可以说)将会话 ID 插入到无 cookie 会话的 URL 中而不进行重定向。 Server.Transfer 在请求生命周期的那个时候是不允许的。我试过了,但收到“执行子请求时出错”消息。

    后来,我在Enabling POST in cookieless ASP.NET Applications 上找到了这篇文章。基本上,通过绑定 Application_EndRequest 事件,您可以检测重定向、清除响应并将表单发布到包含会话 ID 的新 URL。

    void MvcApplication_EndRequest(object sender, EventArgs e)
    {
    
        HttpApplication application = (HttpApplication)sender;
    
        if (application.Request.Form["CorpLogin"] == "1"
            && application.Response.RedirectLocation != null
            && application.Response.IsRequestBeingRedirected)
        {
    
            StringBuilder build = new StringBuilder();
            build.Append("<html>\n<body>\n<form name='Redirect' method='post' action='");
            build.Append(application.Response.RedirectLocation);
    
            build.Append("' id='Redirect' >");
            foreach (string key in application.Request.Form)
            {
                if (key != "CorpLogin")
                    build.Append(string.Format("\n<input type='hidden' name='{0}' value = '{1}'>", (string)key, application.Request.Form[(string)key]));
            }
    
            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>");
    
            application.Response.Clear();
            application.Response.ClearHeaders();
            application.Response.Output.Flush();
    
            application.Response.Write(build.ToString());
    
        }
    }
    

    恕我直言,这不是一个理想的解决方案,但它可能足以满足要求。

    【讨论】:

    • 您能否展示您如何检测到 EndRequest 中的重定向并清除响应?我只需要一点,我想……
    【解决方案2】:

    当 MVC 站点发出重定向时,您是使用控制器自己处理,还是由您的会员提供商自动路由?

    如果您可以在重定向之前拦截请求,您可以将用户名和密码放在 TempData 变量中并在重定向之后处理它。

    【讨论】:

    【解决方案3】:

    您正在寻找 Server.Transfer equivalent in MVC(请参阅 Simon 的回答。)

    它类似于 Request.Redirect,但只是将 .NET 处理转移到另一个页面。它还允许在传输之间的 POST 上维护表单变量(在本例中为 RouteValueDictionary)。

    编辑:(回复您的评论 #1)

    这是Forms Authentication with MVC 的示例。在不知道您的授权机制的内部情况下,我并不完全确定。在“DoLogin”过程的任何时候,您都可以进行转移而不是重定向。

    【讨论】:

    • 我会在哪里拦截第一个无会话表单帖子以防止在创建会话后默认 302 重定向?
    • 查看我的编辑 - 也许它会为您指明正确的方向。
    猜你喜欢
    • 2016-08-20
    • 2010-12-20
    • 1970-01-01
    • 2019-09-27
    • 2012-01-17
    • 2020-03-11
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    相关资源
    最近更新 更多