【问题标题】:Maintaining session via query string in PHP通过 PHP 中的查询字符串维护会话
【发布时间】:2015-07-28 18:28:52
【问题描述】:

php.net 说:

PHP 中的会话支持包括一种跨平台保存某些数据的方法 后续访问。

访问您网站的访问者被分配了一个唯一的 ID,即所谓的 会话 ID。这要么存储在用户端的 cookie 中,要么是 在 URL 中传播。

我正在尝试查看第二个选项,即 php 通过查询字符串传递会话 ID。我这样做只是为了教育目的。我知道不建议这样做。

重现我的实验:

我在 /var/www/html/script.php 中存储了以下脚本:

<?php  
  session_start();
  if (isset($_SESSION["accesses"])) ++$_SESSION["accesses"];
  else $_SESSION["accesses"] = 1;
  echo "This page has been accessed ", $_SESSION["accesses"], " times";
?>

用php.ini中的默认php设置,即:

session.use_cookies = 1
session.use_only_cookies = 1
session.use_trans_sid = 0

一切正常。也就是说,当我在浏览器中访问 localhost/script.php 并刷新页面几次时,计数器会按预期工作。

当我在浏览器中禁用 cookie 时,当我多次刷新页面时计数器不再起作用(它一直保持为 1)。然后我在网上读到,默认情况下,通过查询字符串维护 php 会话是关闭的。然后我去修改php.ini如下:

session.use_cookies = 0
session.use_only_cookies = 0
session.use_trans_sid = 1

用 apache2 重新加载后

service apache2 reload

脚本中的计数器无论如何都不起作用。我在 php.ini 中尝试了更多设置组合,但没有成功。

我使用 PHP 5.5.9 和 Apache 2.4.7。

问题:

我的理解是,当在 php.ini 中禁用 cookie 并启用通过查询字符串传递会话 id 时,在第一次 GET 之后,php 应该看到查询字符串中没有会话 id。然后 php 将为用户初始化一个会话 id 并发送一个响应,该响应会将客户端重定向到与查询字符串中的会话 id 相同的 URL。这一切都是在不编写任何代码的情况下发生的——它是由 php 模块来维护会话的。

这至少是我所期望的。这有多少是真的?我是否对 PHP 自动执行的操作做了很多假设?但是如果我这样做了,那么“这要么存储在用户端的 cookie 中,要么在 URL 中传播”是什么。关于 php.net 关于? 如果 _SESSION 在 cookie 被禁用时不起作用,不应该简单地说吗?

编辑:

下面要回答的其他 cmets:

谜团解开了。通过查询字符串维护会话的工作原理如下面加星标的答案所示。为了查看它的实际效果,我将 /var/www/html/script.php 中的脚本修改为:

<?php  
  session_start();
  if (isset($_SESSION["accesses"])) ++$_SESSION["accesses"];
  else $_SESSION["accesses"] = 1;
  echo "This page has been accessed ", $_SESSION["accesses"], " times";
  echo '<br><a href="script.php">revisit</a>';
?>

你可以看到简单的刷新页面被PHP视为多次 尝试初始化一个新会话。只有当您单击“重新访问”链接时,会话 ID 才会实际嵌入(由 PHP 自动)在链接中,并且计数器开始工作(从那时起,它会通过再次访问链接或刷新来增加)。

关于 php.ini 中的设置的更多信息 (注意:我在 Firefox 39.0 中进行了以下所有实验。在其他浏览器中行为可能会有所不同。):

选项 1: 如果您希望 PHP 使用 cookie 来维护会话(如果它们在客户端浏览器中启用)并使用查询字符串(如果 cookie 被禁用),请确保您的 php.ini 具有以下设置:

session.use_cookies = 1
session.use_only_cookies = 0
session.use_trans_sid = 1

第一个默认启用(至少在我的 PHP 版本中,见上文)。其余两个是从默认值修改的。您需要修改两者

这是如何工作的很有趣,因为当您执行第一个 GET 请求时,您不会在查询字符串中传递会话 id 并且未设置 cookie,因此 PHP 不知道 是否应该重写链接(请参阅下面带星标的答案)或设置 cookie(可能会失败)。

它的作用是尝试两者:您可以看到,在第一次访问时,下面示例中的“revisit”链接被 php 重写为包含会话 ID,但也是来自服务器的第一个响应尝试设置一个饼干。

只有在第二次请求之后,PHP 才知道 cookie 是否被成功植入。如果是,则不再重写链接。如果没有,它会不断重写链接以在查询字符串中包含会话 ID。

选项 2: 如果您希望 PHP 使用 cookie 来维护会话(如果它们在客户端浏览器中启用),但在禁用 cookie 时不使用查询字符串,请坚持使用默认设置,即:

session.use_cookies = 1
session.use_only_cookies = 1
session.use_trans_sid = 0

选项 3: 如果您希望 PHP 专门使用查询字符串来维护会话(不推荐),即使启用了 cookie,请使用:

session.use_cookies = 0
session.use_only_cookies = 0
session.use_trans_sid = 1

请注意,这些与默认的 PHP 设置完全相反。这是有充分理由的。

【问题讨论】:

  • querystring 中使用session id 可以导致session hijacking
  • @DarkBee 这个问题承认这一点:“我这样做只是为了教育目的。我知道不建议这样做。”
  • 如果你输入: session_regenerate_id(); 你可以让黑客更难劫持会话:就在会话开始代码下方。

标签: php apache session cookies


【解决方案1】:

我是否对 PHP 自动执行的操作假设过多?

是的,这部分不会发生:

然后 php 将...发送一个响应,将客户端重定向到相同的 URL,查询字符串中带有会话 ID。

PHP 对该选项的作用是重写页面中的链接,以便当您点击进入下一页时,会话ID 将被保留。没有什么会迫使您离开没有会话 ID 的页面,这只是被视为创建新会话的标志。

因此,当您通过刷新同一页面进行测试时,就像刷新登录表单而不是提交它一样——您是在告诉 PHP 每次都开始一个新会话。

(注意:我从来没有真正使用过这个功能,所以我可能完全错了,欢迎礼貌指正。)

【讨论】:

    【解决方案2】:

    因为查询字符串中的会话 ID 绝对不被推荐,但在 PHP 4.2.0+ 中是可能的,大多数主机默认在你的 apache 配置中禁用它们。只需检查这一行的 apache/vhost/htaccess 配置:

    php_flag session.use_trans_sid off
    

    更新 (感谢 IMSoP):要检查 session.use_trans_sid 是否在某处被禁用,您只需将 phpinfo(); 添加到您的脚本并检查设置的值。 em>

    如果您使用的 PHP 版本早于 4.2,则必须使用 --enable-trans-sid 参数编译 PHP,请参阅 PHP 手册:

    除非您使用的是 PHP 4.2.0 或更高版本,否则您需要启用它 构建PHP时手动。在 Unix 下,通过 --enable-trans-sid 到 配置。 http://de2.php.net/manual/en/session.idpassing.php

    如果你这样做了,你可以像你已经做的那样启用session.use_trans_sid,PHP 会关心这个 ID。

    否则,您必须手动保留 ID,例如:

    <?php echo 'mypage.php?'.htmlspecialchars(SID); ?>
    

    【讨论】:

    • 您引用的文字说“除非您使用的是 PHP 4.2.0 或更高版本”,而不是“或更早版本”。该说明适用的任何版本都属于博物馆。
    • 你是对的。这是推理中的错误...我很确定较新的 PHP 版本默认禁用 trans_sid,反之亦然。我扩展了我的答案。
    • OP 已经提到编辑 php.ini,所以我认为这不会增加他们已经知道的任何内容。
    • 公平点。在这种情况下可能值得添加的一件事是,您可以使用 phpinfo() 检查设置的值
    • 我在修改 php.ini 以检查并启用 use_trans_sid 后尝试了 phpinfo()。我不需要更改任何 Apache 的设置。
    猜你喜欢
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    相关资源
    最近更新 更多