以最优雅的方式从无效的会话ID中恢复

时间:2014-08-22 16:29:34

标签: php regex session cookies sessionid

最近,我在日志中收到以下错误:

PHP Warning:  session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in [...] on line [..]
PHP Warning:  Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0
PHP Warning:  Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php5) in Unknown on line 0

this previous question的答案足以检测转移这样的场景,这样就不会产生错误,但我对最优雅的<感兴趣< EM>恢复;也就是说,以有效的新(空)会话结束。

首先,对检测和检测进行了一些改进。转移代码在上一个问题中,现在已有六年了:

  1. 现在,会话更有可能通过cookie完全处理。我的php.ini中的session.use_only_cookies标志已启用,由于我不记得更改它,我认为这是默认值。

  2. 有效会话ID中使用了哪些字符,以及这些字符中有多少字符取决于php.ini中的session.hash_functionsession.hash_bits_per_character值。我的值分别是0和5,除非我弄错了,这意味着我自己的会话ID应该与正则表达式/^[a-v0-9]{26}$/匹配。我认为这些也是默认值。

  3. 可以使用php.ini中的session.name自定义用于存储会话的cookie的名称。始终可以使用session_name()函数检索正确的值。

  4. 鉴于这些,最优雅的转移方式(可能)如下:

    function my_session_start() {
      if (!isset($_COOKIE[session_name()]) || preg_match('/^[a-v0-9]{26}$/', $_COOKIE[session_name()]) !== 0) {
        return session_start(); // since 5.3, returns TRUE on success, FALSE on failure.
      }
      else {
        return false;
      }
    }
    

    至于恢复(将替换return false;块中的else),one answer to the previous question建议如下:

    session_id(uniqid());
    session_start();
    session_regenerate_id();
    
    然而,我担心这种恢复方式只收到两份赞成票而没有评论,但未得到充分的审查。

    this question的答案表明内部session_start()函数直接依赖 $_COOKIE[session_name()],而不是该值的其他内部表示。是这样的吗?如果是这样,具有检测和恢复功能的my_session_start()函数可以如下所示:

    function my_session_start() {
      if (isset($_COOKIE[session_name()]) && preg_match('/^[a-v0-9]{26}$/', $_COOKIE[session_name()]) === 0) {
        unset($_COOKIE[session_name()]);
      }
    
      return session_start();
    }
    

1 个答案:

答案 0 :(得分:3)

我只在$_COOKIE['PHPSESSID'] === ''时才看到这种情况发生。当有人使用Firebug来清除cookie&#34;时会发生这种情况。我只想处理这个具体情况;如果会话ID以其他方式无效,我想收到警告。处理我的具体用例很简单:

$session_name = session_name();
if (isset($_COOKIE[$session_name]) and empty($_COOKIE[$session_name])) {
    // This happens when someone does "clear cookie" in Firebug; it causes session_start()
    // to trigger a warning. session_start() relies on $_COOKIE[$session_name], thus:
    unset($_COOKIE[$session_name]);
}
session_start();

出于好奇,你真的需要处理除了空字符串之外的任何场景吗?如果恶意进行(为了触发警告),它可能只是其他东西,但由于你在生产中禁用display_errors,没有人可以从中获取任何信息。