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

Php 以最优雅的方式从无效会话id中恢复,php,regex,session,cookies,sessionid,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 characte

最近,我的日志中出现以下错误:

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
答案足以检测和转移此类场景,因此不会产生错误,但我对最优雅的恢复感兴趣;也就是说,以一个有效的新(空)会话结束

不过,首先,对前一个问题中的探测和转移代码进行了一些改进,该问题已经有六年历史了:

  • 如今,会话更可能完全通过cookie进行处理。我的php.ini中的
    session.use_only_cookies
    标志已启用,因为我不记得更改过它,所以我假设这是默认值

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

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

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

    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;
      }
    }
    
    至于恢复(将替换
    else
    块中的
    返回false;
    ),建议如下:

    session_id(uniqid());
    session_start();
    session_regenerate_id();
    
    然而,我担心的是,这一恢复手段只收到了两张赞成票,没有得到任何评论,没有得到充分的审查

    对的回答表明,内部的
    session\u start()
    函数直接依赖于
    $\u COOKIE[session\u name()]
    的值,而不是该值的其他内部表示形式。是这样吗?如果是这样,则具有检测和恢复功能的
    my\u session\u 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();
    }
    

    我只在
    $\u COOKIE['PHPSESSID']='
    时见过这种情况。当有人使用Firebug“清除cookie”时,就会发生这种情况。我只想处理这个特定的场景;如果会话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\u errors
    ,因此没有人可以从中获得任何信息