似乎挺多人不知道 PHP 可以通过 URL 甚至请求体来传递 SESSION_ID

2024/12/02 计算机网络

由于HTTP是无状态的,服务端不知道前一个访问者跟后一个访问者是否为同一人,于是会话机制出现了。sessioncookie几乎总是同时出现的。cookie是由服务端创建、由客户端保存的小块数据,在用户再次访问服务时,会带上该服务端对应的cookie,服务端比对后就能辨别出用户身份。而在服务端跟cookie对应的数据就称为session

从以上描述可以发现,会话中的cookie是由服务端生成的且要唯一识别用户,称为session_idPHP默认通过cookie传递session_idHTTP协议中的响应头Set-Cookie就是用来干这活的,HTTP响应报文无非就响应头和响应体,不用Set-Cookie行不行?当然,自己实现一套session机制也是可以的;既然服务端可以通过其它响应头或响应体来传递session_id,那客户端是不是也能不通过Cookie请求头来传递session_id?确实也可以。

通过 URL 传递

PHPsession机制除了通过cookie来传递session_id外,还可以通过URL参数来传递,详情查看 https://www.php.net/manual/en/session.idpassing.php一节。测试代码如下:

<?php

ini_set('session.use_only_cookies', 0);
ini_set('session.name', 'phpsid');

session_start();

if (isset($_GET['init'])) {
    $_SESSION['name'] = 'lwlinux';
    echo session_id(), PHP_EOL;
}

print_r($_SESSION);

PHP出于安全的考虑,默认只允许通过cookie传递session_id,为了通过URL传递,需要将session.use_only_cookies禁用,同时为了便于测试,可以设置一个易记的session.name。以下命令完整地测试了创建session、无参数无法获取sessionURL传参获取session三个功能。至于session_id在客户端怎么保存就不用提了。

$ curl http://php84.id/programming_practice/php/snippets/php.php?init
73c6fa808fc7e2074a3c68e40b412f3d
Array
(
    [name] => lwlinux
)
$ curl http://php84.id/programming_practice/php/snippets/php.php
Array
(
)
$ curl http://php84.id/programming_practice/php/snippets/php.php?phpsid=73c6fa808fc7e2074a3c68e40b412f3d
Array
(
    [name] => lwlinux
)

通过请求体传递

通过URL传递session_id会存在安全风险,不过在客户端禁用cookie时那也是没办法的,可以使用https等方式来加强安全,只不过URL会保留在访问记录中,依然不安全。事实上,PHP还可以通过请求参数来传递,对比上述PHP代码,多了获取phpsid请求体参数并使用session_id()函数设置当前会话ID的逻辑。

<?php

ini_set('session.use_only_cookies', 0);
ini_set('session.name', 'phpsid');

session_start();

if (isset($_GET['init'])) {
    $_SESSION['name'] = 'lwlinux';
    echo session_id(), PHP_EOL;
}

if (!empty($_POST['phpsid'])) {
    session_id($_POST['phpsid']);
}

print_r($_SESSION);

沿用上面生成的session_id,对比测试一下是否带参数即可。

$ curl http://php84.id/programming_practice/php/snippets/php.php
Array
(
)
$ curl -d 'phpsid=73c6fa808fc7e2074a3c68e40b412f3d' http://php84.id/programming_practice/php/snippets/php.php
Array
(
    [name] => lwlinux
)

Search

    Table of Contents