代码之家  ›  专栏  ›  技术社区  ›  Brian MacKay

在页面之间传递数据的最佳实践

  •  64
  • Brian MacKay  · 技术社区  · 14 年前

    问题

    会话丢失本身就是一个问题,尽管它是 主要地

    这些问题中的大多数都有解决方法,但当我逐渐解决时,所有这些摩擦让我感觉使用session在页面之间传递数据是错误的方向。

    建议的解决方案

    会话

    如上所述,严重依赖会话 似乎 这是个好主意,但它会打断后退按钮并导致其他一些问题。

    使用session非常好的一点是,篡改不是一个问题。与通过未加密的QueryString传递所有内容相比,您最终编写的保护代码要少得多。

    跨页过帐

    事实上,我几乎没有考虑过这个选择。我有一个问题,它使页面紧密耦合-如果我开始做PreviousPage.FindControl(“SomeTextBox”),这似乎是一个维护问题,如果我想从另一个页面,可能没有一个控制称为SomeTextBox。

    在其他方面似乎也很有限。例如,我可能想通过一个链接进入这个页面。

    我现在倾向于这个策略,就像以前一样。但我可能希望我的查询字符串被加密,使其更难篡改,我想处理的问题,重放攻击以及。

    there's an article about this

    但是,应该可以创建一个HttpModule来处理所有这些,并从页面中删除所有加密。果然, Mads Kristensen has an article where he released one. 不过,这些评论让人觉得它在极为常见的场景中存在问题。

    当然,这不是一个夸张的选择,而是我正在考虑的主要选择。 This link

    那么,您如何处理在页面之间传递数据的问题呢?你必须解决哪些隐藏的问题,有没有什么现成的工具可以完美地解决这些问题? 你觉得你有一个完全满意的解决方案?

    提前谢谢!

    更新:

    6 回复  |  直到 9 年前
        1
  •  42
  •   Thomas    14 年前

    首先,您要处理的问题与在无状态环境中处理状态有关。你所面临的困难并不新鲜,这可能是使web开发比windows开发或可执行文件开发更困难的原因之一。

    • 查询字符串-查询字符串适用于向数据(例如主键值)或状态值传递指针。查询字符串本身不应被认为是安全的,即使由于重放而加密。此外,有些浏览器对url的长度有限制。但是,查询字符串有一些优点,例如可以将其添加到书签并通过电子邮件发送给其他人,如果不与其他任何东西一起使用,它们本身就是无状态的。

    • 表单数据-表单数据可能会占用大量信息,但代价是发布时间和某些情况下的重新加载时间。ASP.NET的ViewState使用隐藏的表单变量来维护信息。使用ViewState之类的工具在页面之间传递数据的优点是使用back按钮可以更好地工作,但是可以很容易地创建巨大的页面,这会降低用户的体验。一般来说,ASP.NET模型不适用于跨页发布(尽管这是可能的),而是适用于返回到同一页并从此处导航到下一页的发布。

    • 会话-会话适用于与用户正在进行的进程相关的信息或常规设置。您可以将相当多的信息存储到会话中,代价是服务器内存或数据库的加载时间。从概念上讲,Session的工作原理是一次从内存或状态服务器为用户加载全部数据。这意味着,如果您有一个非常大的数据集,您可能不想将其放入会话中。会话可能会产生一些后退按钮问题,这些问题必须与用户实际尝试完成的任务进行权衡。一般来说,您会发现后退按钮可能是web开发人员的祸根。

    • 数据库—最后一种解决方案(也可以与其他方案结合使用)是将数据库中的信息存储在适当的模式中,并使用一列指示项的状态。例如,如果您正在处理订单的创建,则可以使用“state”列将订单存储在order表中,以确定它是否是真实的订单。您可以将订单标识符存储在查询字符串或会话中。网站将继续向表中写入数据,以更新各个部分和子项,直到最终用户能够声明它们已完成,并且订单的状态被标记为真实订单。这会使报告和查询复杂化,因为它们都需要区分“真实”项目和正在处理的项目。

    在后面的链接中提到的项目之一是应用程序缓存。我不认为这是特定于用户的,因为它是应用程序范围的(很明显,它可以成为特定于用户的,但我也不建议这样做)。除了将数据传递给处理程序或模块之外,我从未在HttpContext中存储数据,但我怀疑它是否与上述解决方案有所不同。

    总的来说,没有一个解决方案可以将它们统统统治。最好的方法是在每个页面上假设用户可以从任何地方导航到该页面(而不是假设他们使用另一个页面上的链接到达该页面)。如果你这样做,后退按钮的问题变得更容易处理(虽然仍然是一个痛苦)。在我的开发过程中,我广泛地使用前四种解决方案,有时在需要时使用最后一种解决方案。

        2
  •  9
  •   Steve    14 年前

    我想说托马斯唯一缺少的是;客户端javascript状态。在我工作的地方,我们发现客户越来越期待“web2.0”类型的应用程序。我们还发现,这类应用程序通常会带来更高的用户满意度。只要稍加练习,再加上一些非常棒的javascript库的帮助,比如jQuery(我们甚至已经开始使用GWT,并发现它非常棒),与WCF中实现的基于JSON的REST服务进行通信就变得微不足道了。这种方法还提供了一种非常好的方法,可以开始转向基于SOA的体系结构,并将UI和业务逻辑完全分离。

    但我离题了。

    在我看来,似乎您已经有了一个应用程序,并且已经扩展了ASP.NET内置会话状态管理的限制。所以。。。下面是我的建议(假设您已经尝试过ASP.NET的进程外会话管理,它比进程内/机箱内会话管理的扩展性要好得多,而且听起来您已经尝试过了,因为您提到了它);NCache。

    NCache为您提供了一个替换ASP.NET会话管理选项的“drop-in”。它非常容易实现,而且可以很好地“创可贴”你的应用程序,让你通过-没有任何重大投资重构你现有的代码库立即。

    只是我的想法。

        3
  •  8
  •   Brian MacKay    13 年前

    在玩了更复杂的会话状态处理(这导致了许多断开的返回按钮等等)之后,我最终滚动了自己的代码来处理加密的查询字符串。这是一个巨大的胜利——我的所有问题场景(后退按钮、同时打开多个选项卡、丢失会话状态等)都得到了解决,而且由于使用非常熟悉,复杂性也降到了最低。

    这仍然不是一个万能的子弹,但我认为它是好的,约90%的情况下,你遇到的。

    细节

    所以你可以打电话:

     SecureRedirect(String.Format("Orders.aspx?ClientID={0}&OrderID={1}, ClientID, OrderID)
    

    CorePage解析出QueryString并将其加密到一个名为CoreSecure的QueryString变量中。所以实际请求如下所示:

    从那里,您可以拨打:

    X = SecureRequest("ClientID")
    

    结论

    使用熟悉的语法,一切都可以无缝地工作。

    在过去的几个月里,我还修改了这段代码来处理边缘情况,比如触发下载的超链接—有时需要在客户端生成一个具有安全查询字符串的超链接。效果很好。

    让我知道如果你想看到这个代码,我会把它放在某个地方。

    最后一个想法:接受我自己的答案而不是其他人在这里发表的一些非常有想法的帖子是很奇怪的,但这确实似乎是我问题的最终答案。感谢所有帮助我到达那里的人。

        4
  •  5
  •   nneonneo    12 年前

    Data pasing methods 我最后的建议是:

    用于:

    • 加密[userId's]
    • 加密[xyzIds..]

    数据库

    • 按COOKIE ID列出的数据集
    • 按COOKIE ID列出的数据表
    • 按COOKIE ID列出的所有其他大块

    我的建议也取决于下面的统计数据和这个链接的细节 数据传递方法

    enter image description here

        5
  •  3
  •   Fosco    14 年前

    只需做一点工作,就可以支持子会话,并允许在不同的选项卡/窗口中执行多任务。

        6
  •  2
  •   Dillie-O    14 年前

    作为一个起点,我发现使用关键数据元素(如客户ID)最好放入查询字符串中进行处理。您可以轻松地跟踪/过滤来自这些元素的坏数据,还可以与电子邮件或其他相关站点/应用程序进行一些集成。

    在重写过程中,我通过“ViewEmployee.aspx?Id=XXX”和“ViewRequest.aspx?Id=XXX”的基本URL提供了雇员Id和请求Id。应用程序被设置为A)过滤掉坏的id,B)在允许用户访问这些页面之前对用户进行身份验证和授权。这允许主要应用程序用户做的是用电子邮件中的URL向审计员发送简单的电子邮件。当他们非常匆忙的时候,他们正处于批量处理时间,他们可以简单地点击一个url列表并进行适当的处理。