【问题标题】:PHP custom session ID, optimized versionPHP自定义会话ID,优化版
【发布时间】:2012-10-16 08:22:31
【问题描述】:

我想实现一个 PHP 自定义会话 ID,同时避免不必要地调用 session_start()

基本上,一种简单的算法是

session_start();
if ( ! isset( $_SESSION['MyStuff'] )) {
  session_write_close();
  session_id( generate_my_id() );
  session_start();
}

$_SESSION['MyStuff'] = some stuff...;

如果会话一开始就过期或不存在,第一个session_start() 将创建自己的 ID 并向浏览器发送 cookie。然后会话结束,并创建另一个会话,发送另一个 cookie(加上创建和关闭会话文件的开销)。

另一种解决方案是测试 PHPSESSID cookie 是否存在,其值是否具有根据 - homecooked - generate_my_id() 函数的格式 - 然后再次测试 $_SESSION 值是否存在。但是,如果会话过期(没有 $_SESSION['MyStuff']),将再次调用不必要的 session_start()

所以问题是,根据我的观察,实际上是两个问题

  • 有没有办法在调用session_start()之前指定PHP应该如何创建会话ID(似乎不可能)?

  • 有没有办法检查session_start() 是否必须创建一个新会话,或者只使用一个可用的服务器端? (这将消除它的第一次调用)

欢迎任何好的选择。

编辑

关于什么是自定义 ID 的说明。

会话 ID 是 PHP 用来在服务器上检索会话的字符串键,每个用户都有不同的键。该密钥通常存储在 cookie 中,然后浏览器将该 cookie 及其请求发送到服务器/PHP 以“连接”到会话。 PHP 根据设置自动设置会话 ID 密钥,基于 MD5(用户和时间相关数据)或 SHA1(相同相关数据)。因此,会话 ID 是 MD5 或 SHA1 密钥 - 希望是唯一的。

自定义 ID 是程序员(我)手动创建的密钥,绕过 md5/sha1 创建。

【问题讨论】:

  • 也许这会有所帮助stackoverflow.com/a/12799253/984422
  • @W 谢谢,但我不知道它在哪里
  • 嗨@ring0 这个怎么样? gist.github.com/3898302
  • @W 这基本上是下面的答案之一,它不起作用,因为 a) 没有自定义 id,b) session_id() 结果在调用 session_start() 之前是没有意义的

标签: php session


【解决方案1】:
  1. 是的,从 5.3 开始,您可以在生成会话 ID 时使用 session.hash_function 指定哈希算法;不建议使用您自己的哈希算法,特别是因为哈希附带的算法已经过广泛的传播、速度、冲突等测试。

  2. 由于 cookie 通常用于维持会话,您可以使用该信息来确定 session_start() 是否会创建新会话。

下面说明了一种方法,可以最大限度地减少您需要的session_start() 语句的数量;它是从现有代码(即OO)推导出来的:

do {
    // discover session by cookie
    if (isset($_COOKIE[session_name()])) {
        session_start();
        // validate session contents
        if (!isset($_SESSION['MyStuff'])) {
            // destroy session and regenerate id
            session_destroy();
            session_regenerate_id(true); // skip this if you generate your own
        } else {
            // validation passed, no need to populate
            break;
        }
    }
    // populate new session
    // you can use session_id($your_id) here
    session_start();
    $_SESSION['MyStuff'] = 'foobar';
} while (false);

奇怪的do { } while 循环只是一个美化的goto,因此如果当前会话有效,您可以跳过第二个session_start()

【讨论】:

  • 我的问题不清楚吗 :-) 1. 如果 cookie 不存在,则无需创建自定义 ID,再加上 2. 如果存在,则调用 2 session_start()无论如何 - 因为 session_regenerate_id() / 实际上应该是 session_id ( MyCustomID ) 因为 s_regenerate_id 不允许自定义创建 / 将运行另一个 session_start()。请再读一遍问题。
  • @ring0 您可以在//populate new session 位置附近添加session_id() 并删除session_regenerate_id() - 这并不遥远;顺便说一句,为什么需要自己生成 id?
  • 需要一个基于我们想要实现的自定义 ID - 抱歉,这不是这里的主题。当会话过期时,您的解决方案仍然需要两个 session_start()(如果没有 cookie,我们将返回我的算法)。
  • @ring0 如果设置了 cookie 但会话未验证,则只需要两个 session_start();我不知道如何避免这种情况。
  • 这是这个问题的目的 :-) 要么强制 session_start() 使用特定算法(无需重写 C 代码!)来生成 ID,要么有办法检测是否有任何会话无需事先致电session_start() 即可在服务器端使用。
【解决方案2】:

迟到的答案,但请检查 changelog for PHP v5.5.1

它引用了一个名为 SessionIdInterface 的新接口,它的唯一方法是 create_sid,尽管它仍然没有记录。

interface SessionIdInterface  {
    public function create_sid ();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 2021-05-18
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    相关资源
    最近更新 更多