我过去曾经严重依赖会话变量,但是最近发现其中许多不必要,而使用查询字符串参数之类的东西。
我的一位同事拒绝使用会话变量。这是一个现实的目标,并且出于任何实际原因应避免使用会话变量吗?是否可以完全避免使用会话变量(除了允许登录的会话cookie之外),这会导致更好的设计吗?
我的同事不使用它们的一些原因:
- 会话变量的无类型性质
- 会话超时导致状态丢失
- 会话变量的全局范围性质
- 负载平衡服务器丢失会话(特定于.Net?)
- 应用程序池/服务器重新启动
- 他们是不必要的
我过去曾经严重依赖会话变量,但是最近发现其中许多不必要,而使用查询字符串参数之类的东西。
我的一位同事拒绝使用会话变量。这是一个现实的目标,并且出于任何实际原因应避免使用会话变量吗?是否可以完全避免使用会话变量(除了允许登录的会话cookie之外),这会导致更好的设计吗?
我的同事不使用它们的一些原因:
Answers:
如果您的应用程序中有一个会话变量,请问问自己:
单击浏览器的后退按钮时,我希望变量具有什么值?
如果答案是“当前值”,则会话变量可能很有用。一个例子就是购物车:当您回顾历史时,您不希望东西从购物车中删除。它始终处于当前状态。
如果答案是“先前的值”,则不应使用会话变量。我见过的不好的用法包括在页面之间传递参数。如果我单击“后退”按钮返回到页面,则该页面不一定获得正确的参数。另外,如果我打开两个标签,那么我的网站会如何运作?
正确实现后退按钮行为绝不是一劳永逸的,但是它可以帮助您将网站视为无状态应用程序。通常,我发现会话变量的适当用法很少。
HTTP协议是无状态的。会话是一种在HTTP请求中保留客户端状态的方法。您可以选择使用平台的内置会话处理来执行此操作,也可以自己使用查询字符串参数来执行此操作。无论哪种方式,会话的某些概念对于许多任务都是必需的。
您的同事可能不喜欢特定的实现,或者没有将会话用于其预期目的。如果需要保留有关HTTP请求中特定客户端连接的信息,则需要某种形式的会话持久性。
以下问题是特定于实现的:
会话变量的无类型性质
会话变量的全局范围性质
负载均衡服务器丢失会话
应用程序池/服务器重新启动
例如,我经常使用PHP并将会话信息存储在关系数据库中。因此,输入了我的会话变量。负载平衡和服务器重新启动不会引起任何会话问题。
这个更有趣:
会话超时导致状态丢失
会话通常是通过Cookie保留的。客户端可以随时删除它们。但是它们也可以通过查询字符串参数保留,因此永远不会在客户端上超时。服务器超时取决于您。因此,即使这个问题也是特定于实现的。
我们不要仅仅因为我们不喜欢特定的实现而放弃整个会话的概念。任何良好的Web应用程序框架都将有助于正确使用会话来保留用户登录名或保留用户当前访问所特有的任何其他内容。用户的数据库记录可以(并且应该)用于在登录时存储特定于他们的内容。但是,匿名访问者可能会在会话中保留一些值得保留的临时信息,例如访问的近期页面的简短列表或隐藏他们已经看过的通知。通常,只有较小的临时信息适合于会话存储。
其他人提出了很多优点(我将避免重复),但是您的伙伴技术的一个方面尚未讨论:安全性。
不看代码就不可能知道您打开了什么样的漏洞,但是我可以想到以下几点。
当您使用Sessions时,所有这些仍然可能发生,但是如果您的好友不知道他在做什么,它们会变得容易得多。
由于经历过一些糟糕的经历,我曾像您的同事一样思考过,我曾调试过与会话变量有关的问题,而这实际上只是我的无能。是的,您可以在某种程度上不使用会话变量,而使用查询字符串,表单中的隐藏字段和其他方式。但是,如果您的应用程序具有超出最基本的逻辑流程来确定状态的任何内容,则以这种方式进行操作非常麻烦。通过查询字符串和隐藏字段显示应用程序的内部工作方式也存在安全风险,其中任何一个都可以用作攻击载体。
使用会话变量时,您只需要跟踪它们的设置和取消设置时间,因为这将确定应用程序的逻辑流程。就像使用C这样的语言进行内存管理一样。
请注意,这只是我的经验,在一个没有框架的相对较小的项目中使用PHP的情况,在其他平台上可能有所不同,但是我认为一般原理仍然适用。
如前所述,HTTP是无状态的,而Session Variable打破了这一点。HTTP设计为无状态有助于缓存资源。对于公开可用的资源。
可以设计一个没有会话变量的网站,但难度更大。最困难的(IMHO)是精美的登录/注销,HTTP身份验证方案不提供通过HTML表单进行身份验证所需的工具(您可能会使用javascript-XHR破解某些东西到https:// untel:passowrd@mydomain.com),并且注销甚至与跨浏览器兼容都更加困难。w3邮件列表对此进行了一些讨论,但是如果我没记错的话,这个想法就被放弃了。
对于其余的内容,您应该可以不使用Session变量。您将在数据库,文件或其他任何位置上都有某种状态,但是很少使用Session变量。
如果您的用户有购物车,则仅当假定该用户能够在两台计算机/浏览器上浏览而不共享购物车时,它才是可变会话。
using things like query string parameters instead
-在这种情况下,请尽可能始终使用查询字符串参数。对于这种类型的参数,使用会话很脆弱,并且当用户打开多个选项卡时可能会引入奇怪的错误。