在客户端的第二次请求中包含的Cookie头部中,提供给了服务器端可以用来标识客户端身份的信息。这时,服务器端也可以判断客户端是否启用了 cookies。尽管,用户可能在和应用程序交互的过程中突然禁用cookies的使用,但是,这个情况基本是不太可能发生的,所以可以不加以考虑,这在实践中也被证明是对的。

  GET and POST Data

  除了cookies,客户端还可以将发送给服务器的数据包含在请求的url中,比如请求的参数或者请求的路径中。 我们来看一个例子:

  GET /index.php?foo=bar HTTP/1.1

  Host: example.org

  以上是一个常规的http get 请求,该get请求发送到example.org域名对应的web 服务器下的index.php脚本, 在index.php脚本中,可以通过$_GET['foo']来获取对应的url中foo参数的值,也是’bar’。大多数php开发者都称这样的数据会GET数据,也有少数称它为查询数据或者url变量。但是大家需要注意一点,不是说GET数据只能包含在HTTP GET类型的请求中,在HTTP POST类型的请求中同样可以包含GET数据,只要将相关GET数据包含在请求的url中即可,也是说GET数据的传递不依赖与具体请求的类型。

  另外一种客户端传递数据到服务器端的方式是将数据包含在http请求的内容区域内。 这种方式需要请求的类型是POST的,看下面一个例子:

  POST /index.php HTTP/1.1

  Host: example.org

  Content-Type: application/x-www-form-urlencoded

  Content-Length: 7

  foo=bar

  在这种情况下,在脚本index.php可以通过调用$_POST['foo']来获取对应的值bar。开发者称这个数据为POST数据,也是大家熟知的form以post方式提交请求的方式。

  在一个请求中,可以同时包含这两种形式的数据:

  POST /index.php?myget=foo HTTP/1.1

  Host: example.orgContent-Type: application/x-www-form-urlencoded

  Content-Length: 11

  mypost=bar

  这两种传递数据的方式,比起用cookies来传递数据更稳定,因为cookie可能被禁用,但是以GET以及POST方式传递数据时,不存在这种情况。我们可以将PHPSESSID包含在http请求的url中,像下面的例子一样:

  GET /index.php?PHPSESSID=12345 HTTP/1.1

  Host: example.org

  以这种方式传递session id的话,可以跟用cookie头部传递session id一样,达到同样的效果, 但是,缺点是需要开发者认为地将session id附加在url中或者作为隐藏字段加入到表单中。不像cookie一样,只要服务器端指示客户端创建cookie成功以后,客户端在后续的请求中,会自动第将对应的没有过期的cookie传递给服务器端。当然,php在开启session.use_trans_sid后,也可以自动地将session id 附加在url中以及表单的隐藏字段中,但是这个选项不建议开启,因为存在安全问题。这样的话,容易泄露session id, 比如有的用户会bookmark一个url或者分享一个url,那么session id也暴露了,加入这个session id还没有过期,那是有一定的安全问题存在的,除非服务器端,除了session id外,还附加了其它方式进行验证用户的合法性!

  尽管以POST的方式来传递session id的话,相对GET的方式来说,会安全的多。但是,这种方式的缺点是比较麻烦,因为这样的话,在你的应用程序中比较将所有的请求都转换成post的请求,这显然是不太合适的。

  Session的管理

  直到现在,我只讨论了如何维护应用程序的状态,只是简单地涉及到了如果保持请求之间的关系。接下来,我阐述下在实际中用到比较多的技术 - Session的管理。涉及到session的管理,不是单单地维持各个请求之间的状态,还需要维持会话期间针对每个特定用户使用到的数据。我们常常把这种数据叫做session数据,因为这些数据是跟某个特定用户与服务器之间的会话相关联的。如果你使用php内置的session的管理机制,那么 session数据一般是保存在/tmp这个服务器端的文件夹中,并且其中的session数据会被自动地保存到超级数组$_SESSION中。一个简单的使用session的例子,是将相关的session数据从一个页面传递(注意:实际传递的是session id)到另一个页面。下面用示例代码1, start.php, 对这个例子加以演示:

  Listing 1 - start.php

  

  session_start();

  $_SESSION['foo'] = 'bar';

  ?>

  continue.php

  假如用户点击start.php中的链接访问continue.php,那么在continue.php中可以通过$_SESSION['foo']获取在start.php中的定义的值’bar’。看下面的示例代码2:

  Listing 2: - continue.php

  

  session_start();

  echo $_SESSION['foo']; /* bar */

  ?>

  是不是非常简单,但是我要指出的话,如果你真的这样来写代码的话,说明你对php底层的对于session的实现机制还不是非常了解透彻。在不了解php内部给你自动做了多少事情的情况下,你会发现如果程序出错的话,这样的代码将变的很难调试,事实上,这样的代码也完全没有安全性可言。

  Session的安全性问题

  一直以来很多开发者都认为php内置的session管理机制是具有一定的安全性,可以对一般的session攻击起到防御。事实上,这是一种误解,php团队只实现了一种方便有效的机制。具体的安全措施,应该有应用程序的开发团队来实施。 像开篇谈到的,没有好的解决方案,只有合适你的方案。

  现在,我们来看下一个比较常规的针对session的攻击:

  用户访问http://www.example.org,并且登录。

  example.org的服务器设置指示客户端设置相关cookie - PHPSESSID=12345

  攻击者这时访问http://www.example.org/,并且在请求中携带了对应的cookie - PHPSESSID=12345