应该避免会话变量吗?


36

我过去曾经严重依赖会话变量,但是最近发现其中许多不必要,而使用查询字符串参数之类的东西。

我的一位同事拒绝使用会话变量。这是一个现实的目标,并且出于任何实际原因应避免使用会话变量吗?是否可以完全避免使用会话变量(除了允许登录的会话cookie之外),这会导致更好的设计吗?

我的同事不使用它们的一些原因:

  • 会话变量的无类型性质
  • 会话超时导致状态丢失
  • 会话变量的全局范围性质
  • 负载平衡服务器丢失会话(特定于.Net?)
  • 应用程序池/服务器重新启动
  • 他们是不必要的

3
using things like query string parameters instead-在这种情况下,请尽可能始终使用查询字符串参数。对于这种类型的参数,使用会话很脆弱,并且当用户打开多个选项卡时可能会引入奇怪的错误。
伊兹卡塔2012年

2
个人推荐-不要听取您同事的任何建议,因为他显然不知道他在说什么。会话超时?他是否没有意识到会话持续时间是由Web应用程序控制的?
2012年

2
@GrandmasterB Ahem。要么不知道他们在做什么,要么在职业生涯中被这些要点中的每一个烧死(我本人已经击中了其中的4个),并且知道应对临时状态的更适当方法。
艾德·詹姆斯

有人可以解释会话状态和打开多个标签之间的关系吗?当您打开一个新标签时,它是否包含上一个标签中的状态?谢谢。

Answers:


41

如果您的应用程序中有一个会话变量,请问问自己:

单击浏览器的后退按钮时,我希望变量具有什么值?

如果答案是“当前值”,则会话变量可能很有用。一个例子就是购物车:当您回顾历史时,您不希望东西从购物车中删除。它始终处于当前状态。

如果答案是“先前的值”,则不应使用会话变量。我见过的不好的用法包括在页面之间传递参数。如果我单击“后退”按钮返回到页面,则该页面不一定获得正确的参数。另外,如果我打开两个标签,那么我的网站会如何运作?

正确实现后退按钮行为绝不是一劳永逸的,但是它可以帮助您将网站视为无状态应用程序。通常,我发现会话变量的适当用法很少。


我同意。一旦考虑了带有多个选项卡的期望语义,通常正确的选择是会话变量或请求参数。
CodesInChaos

我已经确切地看到了带有会话变量的这些类型的错误,并且坦率地了解了自己的辛苦方法。
Tjaart

当用户单击“后退”按钮时,他们是否希望这些商品保留在购物车中直到会话结束,还是希望这些商品一直保留到取出?使用其他一些持久性机制(例如数据库)将允许在单个会话之外进行持久化,并且后退按钮仍将按用户期望的方式工作。
Lawtonfogle

25

HTTP协议是无状态的。会话是一种在HTTP请求中保留客户端状态的方法。您可以选择使用平台的内置会话处理来执行此操作,也可以自己使用查询字符串参数来执行此操作。无论哪种方式,会话的某些概念对于许多任务都是必需的。

您的同事可能不喜欢特定的实现,或者没有将会话用于其预期目的。如果需要保留有关HTTP请求中特定客户端连接的信息,则需要某种形式的会话持久性。

以下问题是特定于实现的:

会话变量的无类型性质

会话变量的全局范围性质

负载均衡服务器丢失会话

应用程序池/服务器重新启动

例如,我经常使用PHP并将会话信息存储在关系数据库中。因此,输入了我的会话变量。负载平衡和服务器重新启动不会引起任何会话问题。

这个更有趣:

会话超时导致状态丢失

会话通常是通过Cookie保留的。客户端可以随时删除它们。但是它们也可以通过查询字符串参数保留,因此永远不会在客户端上超时。服务器超时取决于您。因此,即使这个问题也是特定于实现的。

我们不要仅仅因为我们不喜欢特定的实现而放弃整个会话的概念。任何良好的Web应用程序框架都将有助于正确使用会话来保留用户登录名或保留用户当前访问所特有的任何其他内容。用户的数据库记录可以(并且应该)用于在登录时存储特定于他们的内容。但是,匿名访问者可能会在会话中保留一些值得保留的临时信息,例如访问的近期页面的简短列表或隐藏他们已经看过的通知。通常,只有较小的临时信息适合于会话存储。


老实说,我在.Net之外的框架方面经验有限。.Net停止为会话设置超时值。会话变量也作为未类型化的字典冒泡到服务器端代码。无论如何,我通常都会将此字典包装在适当类型的类中,因此我也不认为这是一个问题。您提到您将会话信息存储在数据库中。在ASP .Net中,否则将在.Net客户端,数据库(自动管理)或单独的Windows服务中处理存储。
Tjaart

您能举一些会议预期目的的例子吗?
Tjaart

@Tjaart:我将最后一段扩大了一点。希望能有所帮助。
Matt S

14

其他人提出了很多优点(我将避免重复),但是您的伙伴技术的一个方面尚未讨论:安全性

不看代码就不可能知道您打开了什么样的漏洞,但是我可以想到以下几点。

  • 会话修复:一种强大的攻击,如果您只需让用户单击URL中已经包含必要信息的链接,它就会稍微容易一些(而不是试图使用户使用已正确设置Cookie的计算机)。
  • SQL注入(或其他恶意输入):永远不要信任来自用户的任何信息。会话变量的优点是永不离开服务器,因此用户无法直接更改它们。虽然你不应该把它清理前的数据会话,你总是可以信任你出去后的值。如果所有内容都通过查询字符串传递,则需要进行大量验证,以确保您不接受恶意输入。
  • 使用伪造的输入破坏数据:与SQL注入类似,您要来回传递多少数据?它有多关键?我可以通过更改查询字符串中的值来更改应用程序的行为吗?我可以通过更改值来破坏服务器上的数据吗?如果我设法破坏服务器上的数据,会影响其他用户吗?(如果您的回答是“否”,我的回答是“您确定吗?您有很多地方需要检查。”)

当您使用Sessions时,所有这些仍然可能发生,但是如果您的好友不知道他在做什么,它们会变得容易得多。


2

会话变量在某种程度上类似于旧的Basic全局变量。用户要负担跟踪它们,它们中的内容,它们的范围以及如何使用它们的负担。就像旧版的BASIC一样。话虽这么说,为什么有人会完全不赞成使用一种显然设计为编程模型(ASP,MVC等)的组成部分且非常重要的部分的机制?

我在使用Session变量时遇到的唯一不好的事情是,这使您难以跟踪它们,并确保它们填充有相关数据并进行处理。

这不是我们以任何方式进行编程时所​​做的事情吗?


1

由于经历过一些糟糕的经历,我曾像您的同事一样思考过,我曾调试过与会话变量有关的问题,而这实际上只是我的无能。是的,您可以在某种程度上不使用会话变量,而使用查询字符串,表单中的隐藏字段和其他方式。但是,如果您的应用程序具有超出最基本的逻辑流程来确定状态的任何内容,则以这种方式进行操作非常麻烦。通过查询字符串和隐藏字段显示应用程序的内部工作方式也存在安全风险,其中任何一个都可以用作攻击载体。

使用会话变量时,您只需要跟踪它们的设置和取消设置时间,因为这将确定应用程序的逻辑流程。就像使用C这样的语言进行内存管理一样。

请注意,这只是我的经验,在一个没有框架的相对较小的项目中使用PHP的情况,在其他平台上可能有所不同,但是我认为一般原理仍然适用。


2
将会话用于控制流中涉及的状态时,如何正确使用多个制表符语义?会话可以很好地用于登录和设置(如属性),但对于大多数其他用途而言,它们的语义并不正确。
CodesInChaos

我不确定,我发布的内容是基于我自己在PHP / MySQL中构建数据库驱动的Web应用程序的有限经验。浏览器中的多个标签通常是如何处理的(我假设这就是您所指的)?
primehunter326

@ primehunter326具有路由参数或查询字符串或隐藏的表单字段。
Casey

0

如前所述,HTTP是无状态的,而Session Variable打破了这一点。HTTP设计为无状态有助于缓存资源。对于公开可用的资源。

可以设计一个没有会话变量的网站,但难度更大。最困难的(IMHO)是精美的登录/注销,HTTP身份验证方案不提供通过HTML表单进行身份验证所需的工具(您可能会使用javascript-XHR破解某些东西到https:// untel:passowrd@mydomain.com),并且注销甚至与跨浏览器兼容都更加困难。w3邮件列表对此进行了一些讨论,但是如果我没记错的话,这个想法就被放弃了。

对于其余的内容,您应该可以不使用Session变量。您将在数据库,文件或其他任何位置上都有某种状态,但是很少使用Session变量。

如果您的用户有购物车,则仅当假定该用户能够在两台计算机/浏览器上浏览而不共享购物车时,它才是可变会话。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.