关于不可知的语言:当请求被登录页面中断时保留HTTP POST数据

关于不可知的语言:当请求被登录页面中断时保留HTTP POST数据

Retaining HTTP POST data when a request is interrupted by a login page

假设用户正在浏览网站,然后执行某些操作来更改数据库(假设他们添加了评论)。但是,当实际添加评论的请求出现时,我们发现我们需要迫使他们登录才能继续。

假设登录页面要求输入用户名和密码,然后将用户重定向回需要登录时要使用的URL。该重定向适用于仅具有GET参数的URL,但是如果请求最初包含一些HTTP POST数据,则现在将丢失。

涉及HTTP POST数据时,谁能推荐一种处理这种情况的方法?

显然,如果需要的话,登录页面可以动态生成带有所有POST参数的表单以将其传递(尽管看起来很混乱),但是即使如此,登录页面仍无法以任何方式重定向用户到其预期的页面,同时将POST数据保留在请求中。

编辑:我应该明确说明一个额外的限制-想象一下,直到用户提交他们的评论,我们才知道是否需要登录。例如,他们的cookie可能在加载表单和实际提交评论之间已经过期。


这是Ajax技术可能会有所帮助的好地方。当用户单击提交按钮时,在实际提交页面之前,在客户端显示登录对话框并与服务器进行验证。

我可以想到的另一种方法是在主页本身中动态显示或隐藏DIV标签中的登录控件。


您可能想调查为什么Django在自己实现之前删除了此功能。这似乎不是特定于Django的问题,而是另一种跨站点伪造攻击。


2个选择:

  • 从登录页面写出凌乱的表单,然后将JavaScript form.submit()写入页面。
  • 让登录页面本身POST到请求页面(带有先前的值),并让该页面的控制器执行登录验证。将其应用到您已经具有的用于检测未登录用户的任何逻辑中(框架会因其执行方式而异)。在伪MVC中:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
            CommentController {
               void AddComment() {
                 if (!Request.User.IsAuthenticated && !AuthenticateUser()) {
                    return;
                 }
                 // add comment to database
               }

               bool AuthenticateUser() {
                 if (Request.Form["username"] =="") {
                    // show login page
                    foreach (Key key in Request.Form) {
                       // copy form values
                       ViewData.Form.Add("hidden", key, Request.Form[key]);
                    }
                    ViewData.Form.Action = Request.Url;

                    ShowLoginView();
                    return false;
                  } else {
                     // validate login
                     return TryLogin(Request.Form["username"], Request.Form["password"]);
                  }
               }
            }

    只需将POST中所有必要的数据存储在会话中,直到登录过程完成为止。或在数据库中存储某种临时表,然后再检索它。显然,这是伪代码,但是:

    1
    2
    3
    4
    5
    6
    7
    8
    if ( !loggedIn ) {
        StorePostInSession();
        ShowLoginForm();
    }

    if ( postIsStored ) {
        RetrievePostFromSession();
    }

    或类似的规定。


    我知道它说的与语言无关,但是为什么不利用您使用的服务器端语言提供的约定呢?如果是Java,则可以通过设置Request属性来保留数据。您将使用控制器来处理表单,检测登录名然后转发。如果设置了属性,则仅使用该数据预填充表单?

    编辑:您还可以使用所指出的Session,但是我很确定,如果您使用Java中的Forward返回登录页面,则Request属性将保持不变。


    在他们提交登录页面的页面上收集数据,然后将其存储在您的后端(数据库?)中,然后他们按照登录顺序隐藏页面上的交易ID或类似内容。完成后,使用后端上的事务ID通过查找将它们返回到他们要求的页面,然后将他们发布的所有数据转储到表单中以再次预览,或者仅运行该页面将运行的任何代码。

    请注意,如果用户需要登录才能发表评论,那么许多系统(例如博客)都会通过使用与发布评论相同的登录字段来解决此问题。


    推荐阅读