首页 » PHP » Session与Cookie

PHP Session

由于HTTP是一个无状态协议,要在多个HTTP交互中维持状态需要有一种应用层的解决方案:

  • 在表单隐藏字段传递ID。
  • 在URL中携带ID。
  • 通过Cookie。

表单隐藏字段的问题在于每个页面都需要存在表单,如注册页面,每次通过下一步引出新页面,且新页面中携带相同的隐藏字段;在URL中携带ID的问题在于把信息暴露给用户,且通过相同的URL就能访问其他人的信息。Cookie是一种解决状态维持的更好方案。PHP通过会话跟踪系统(session tracking system)封装了对Cookie的使用(参考php.ini中session的相关配置)。

启动session,并查看session:

if(!isset($_SESSION)) {
    session_start();
}

var_dump($_SESSION);

输出

array(0) { }

可见session里没有内容。通过浏览器访问页面,可以看到Cookie中有一个PHPSESSID的设置:

PHPSESSID=ncpjjli7ojtidgtbtce75s6ne5

在服务器端的session路径下,也生成了一个新文件:sess_ncpjjli7ojtidgtbtce75s6ne5。这个文件是空的,正好对应了$_SESSION。我们再通过session_name()和session_id()查看:

echo session_name()."\n";
echo session_id()."\n";

输出:

PHPSESSID
ncpjjli7ojtidgtbtce75s6ne5

通过PHPSESSID,PHP就唯一识别了一个用户。我们可以修改PHPSESSID的名称以及它的值,如:

session_name("MYSESSION");
session_id(sha1(mt_rand()));

echo session_name()."\n";
echo session_id()."\n";

输出:

MYSESSION
4684933d389aebc83fa9d289d4d3220597786fdc

我们把session_name("MYSESSION")和session_id(sha1(mt_rand()))注释掉,再看session_name()和session_id():

//session_name("MYSESSION");
//session_id(sha1(mt_rand()));

echo session_name()."\n";
echo session_id()."\n";

输出:

PHPSESSID
ncpjjli7ojtidgtbtce75s6ne5

可见还原为了之前的默认ID名称和值。接下来我们在$_SESSION中存储一些值:

f(isset($_GET["username"])) {
    $_SESSION["username"] = $_GET["username"];
}

echo @$_SESSION["username"];

如果用户提交了username,则把它记录在session中。在浏览器地址栏输入:

http://www.berlinix.com/session.php?username=berlinix

页面将输出:berlinix。可见username被保存在了session中。与此同时,我们可以检查session文件:

$ cat sess_ncpjjli7ojtidgtbtce75s6ne5
username|s:8:"berlinix";

再次用浏览器访问:

http://www.berlinix.com/session.php

同样将输出:berlinix。如果我们在命令访问这个页面:

$ curl http://www.berlinix.com/session.php

没有任何输出。接下来,我们伪造一个Cookie,将它发到服务器端窃取用户名:

$ curl http://www.berlinix.com/session.php --cookie "PHPSESSID=ncpjjli7ojtidgtbtce75s6ne5" 
berlinix

通过PHPSESSID,我们窃取了这个ID对应的session信息。

分享

0