首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

无状态的状态(1)

无状态的状态(1)

“状态” 和 “持久化” 是计算的关键术语。这些概念对于计算来说非常普遍,但是如果脱离上下文,就很难理解其含义。清楚地理解这些概念对于现代分布式应用程序的开发人员很重要。
总的来说,“状态” 是指关于程序当前的执行状况的信息 —— 存储在内存中的运行时数据。与之相反,“持久化” 是指在程序的各次执行之间保存数据。对于访问数据库中某个表的程序,数据库本身负责 “持久化”,而关于当前显示的行的信息就是 “状态”。
当 “状态” 这个词应用于协议时,是指每次执行的一系列交互具有连续性,就像程序的状态一样。而在 “无状态” 协议中就没有这种连续性;每个请求都是完全单独处理的。HTTP 就是一种无状态协议。
HTTP 的定义传统上把 HTTP 称为无状态协议(参见 ),意味着这或多或少是最明显的特征。HTTP 本质上由一个请求和一个响应组成:浏览器请求一个特定 URL(可能还提供补充数据),服务器用一个响应页面来应答。尽管最终用户可能觉得他们的网上冲浪过程由一系列连续的步骤组成,但是对于协议来说,每个交付的页面都是相互独立的;任何显示仅仅是与最近的 URL 请求对应的输出。
那么,Web 开发人员所说的 “会话”、“登录”、“注销”、“个性化”、“hijacking” 等有状态概念是如何实现的?其他一些设备补充了 HTTP,为它提供了状态功能;也就是说,服从 HTTP 定义的标准提供了可以解释为状态接口的机制(和其他功能)。   
大多数 Web 框架和浏览器层高级接口(例如可编程的 Session 对象)简化了 Web 开发。但是,总的来说,它们都是把下面的会话维护机制封装在一个抽象接口中。
注意,详细讨论这些框架和接口超出了本文的范围。关于这些技术的更多信息,参见 。
HTTP 交互混淆了状态和持久化之间的差异。开发人员可能把通过一次浏览会话保存的数据称为 “状态”,而把浏览会话之间保存的数据称为 “持久化”。另外,一些人可能把用户浏览器保存的数据称为 “状态”,把服务器保存的数据称为 “持久化”。在现代计算环境中,常常以不一致的方式使用基本术语。本文用 “状态” 表示客户机保存的数据,用 “持久化” 表示服务器保存的数据;这大致符合原始的 “cookie” 规范,这个规范把 cookie 描述为 “在客户端提供持久化状态”(参见 )。
客户端状态可以在客户机程序中存储状态,而且这对于大多数应用程序是合适的。如果状态总是由客户机提供,服务器就是无状态的(至少从程序员的角度来看):不会维护数据,只需处理传入的数据。
cookie“cookie” 规范是由 Netscape 在很久以前引入的。这个名称来自把标识符称为 “magic cookie” 的传统(MIT 的习惯)。cookie 可以把名称/值对与给定的 URL 关联起来,但是一般来说可以跨域设置它们。早期的浏览器容易受到攻击,黑客可以通过许多欺骗技术盗取个人信息,这使许多用户禁用了 cookie 或者定期删除 cookie。在默认情况下,cookie 会在浏览器关闭时过期;但是,指定了过期日期的 cookie 会一直存活到过期日期,即使用户关闭并重新打开浏览器,它们仍然是有效的。许多最佳实践规范建议不使用这些 “持久化” cookie。它们的可靠性不好(许多浏览器可以配置为在退出时清除所有 cookie,甚至包括持久化 cookie),而且会增加安全风险。如果必须使用它们,就要认识到它们不总是有效的。所以,在持久化 cookie 不可用的情况下,需要有其他解决方案。这意味着其实并不需要持久化 cookie。
尽管 cookie 现在由一个标准指定(RFC 2965,“HTTP State Management Mechanism” —— 参见  中的链接),但是用户仍然不信任它们的功能,而且这种不信任常常是有道理的。cookie 本质上是不安全的,它们要求浏览器提供更多的安全限制。另外,cookie 以明文发送,所以在 cookie 中存储私密数据(比如用户名或密码)是很危险的。由于有这些安全问题,无法可靠地跨多个 Web 站点使用 cookie。许多浏览器拒绝处理不属于当前页面的域的 cookie。另外,cookie 不能区分共用一台计算机的多个用户,因此更危险。尽管如此,cookie 有时候是有用的。如果使用得当,它们可以作为状态处理机制的组成部分。如果对所有东西都使用 cookie,就不合适了。因为 cookie 不总是有效,所以还需要了解其他状态机制。
表单、方法和操作过去有两种通过客户机提供状态的方法;这两种方法在表单上很常见。第一种方法是把状态信息附加到 URL 后面,作为 CGI 程序或其他程序的参数。第二种方法是使用 HTTP POST 提交参数。
在许多情况下,把参数附加到 URL 后面非常简单。另外,与 POST 参数相比,它有一个显著的优点:可以创建任意复杂的 URL 并在标准的链接标记中使用,不需要创建表单和提交按钮。
另一方面,POST 也有优点。最显著的优点之一是,POST 数据不会成为用户浏览器历史的一部分。另外,因为 HTTP 规范强烈建议 GET 操作应该是 “等幂” 的(多个获取操作应该只影响本身,而没有持久的影响),所以如果 GET 操作有副作用(比如用信用卡支付或取消预约),用户可能会非常吃惊。对于有副作用的任何东西,最好使用 POST。
当然,POST 参数和 URL 后缀都不安全,容易被编辑。有许多购物车应用程序把价格存储在用户可编辑的参数中,这导致了安全漏洞。另外,用户可能把 URL 做成书签或共享 URL,这对于依靠 URL 机制存储状态的系统非常不利。应该避免用 URL 存储状态。用 POST 数据存储状态要好一些,但是这要求用户会话中的每个链接都是一个表单提交。这两种方法都有显著的缺点。尽管它们对于表单数据和交互非常合适,但是不太适合维护状态。cookie 可能更好。
Ajax 和 XMLHttpRequest在涉及 Web 访问时,使用 Ajax 或相似技术的页面用 “状态” 表示正在运行的程序的内部程序状态,这进一步模糊了状态和持久化数据之间的界限。基于 Ajax 的应用程序使用 JavaScript 变量控制状态;然后,用这些变量决定要提交的新请求。XMLHttpRequest 是 JavaScript(或其他脚本语言)用内部状态动态地更新 Web 页面的一种方式。
在实践中,许多用户禁用了 JavaScript 或限制了其部分功能,所以依靠 JavaScript 实现核心功能常常不合适。可移植性问题和不一致的实现也严重限制了 JavaScript 作为实现语言的作用。尽管 JavaScript 比较适合前沿用户,但是大量用户还在使用老式浏览器,JavaScript 不适合这些浏览器。
JavaScript 实现的安全漏洞可能给用户带来出乎意料的风险,他们可能因此怪罪您的 Web 站点。曾经有一些站点由于不谨慎的 JavaScript 编程方法而受到攻击。
插件和其他扩展浏览器插件可以维护自己的状态,这些状态可能跨也可能不跨浏览器持久会话。Flash 插件过去使用 cookie(见下文),现在仍然可以这样做,但是又增加了对 “Local Shared Objects(LSO)” 的支持,LSO 有可能是很大的二进制对象(不仅仅是纯文本)。引入 LSO 似乎是为了存储游戏高分列表这样的东西,但是也可以用于其他许多用途。随着用户对安全问题越来越敏感,插件厂商也开始提供安全特性。一旦安全特性出现了,原来的一些数据存储方法就会被逐渐禁用或清除,cookie 目前的情况就是这样。
所有基于插件的机制都有一个缺点:用户可能没有安装这个插件,也可能无法获得这个插件。插件可能没有针对某一平台的版本,或者用户所在公司的 IT 部门不允许安装插件。Linux® 或 UNIX® 用户在使用依赖于浏览器插件的站点时可能会遇到困难。如果希望符合标准,就必须找其他办法。
插件的许多问题也出现在 “webOS” 上,webOS 尝试在 Web 上模拟桌面环境。当然,虚拟文件系统或相似的机制可以存储状态,但是用户必须有这些系统。
返回列表