>我正在查看PHP会话文件的内部表示形式,我注意到会话密钥由管道字符|
分隔。
在进入我遇到的问题之前,让我简要介绍一下会话文件的格式。至少,这是我在Mac上的格式化方式(10.9.4,PHP 5.4.24(。
会话文件格式
假设我有以下代码:
$_SESSION["age"] = 26;
$_SESSION["car"] = "Mazda";
$_SESSION["nerdy"] = true;
$_SESSION["likes"] = array(42, "being meta");
$_SESSION["stats"] = array("bmi" => 1000);
然后它像这样存储在会话变量中:
age|i:26;car|s:5:"Mazda";nerdy|b:1;
likes|a:2:{i:1;i:42;i:2;s:10:"being meta"}
stats|a:1:{s:3:"bmi";i:1000}
一般格式为
session_key|session_value[;session_key|value] etc.
其中session_value
是一般形式
type[:size]:value
更具体地说(如果有人感兴趣(,
- 字符串:
s:3:"some text"
- 整数:
i:4
- 布尔值:
b:1
(真(或b:0
(假( - 数组:
a:2:{session_value;session_value;session_value;session_value}
2 的数组中的四个session_value
是key;value
key;value
对。
问题所在
您可以看到,在上面,顶级会话密钥由|
字符分隔。但是,如果我们的会话键名称之一包含|
字符怎么办?
好吧,我试过了。当我这样做时,整个会话文件(以/tmp
为单位(都是空白的(并且绝对没有设置变量(。这是PHP开发人员的疏忽还是未记录的限制(或者是否记录在某处(?
这可以通过将 $_SESSION 键本身放在引号中或在 $_SESSION 键字符串中反斜杠任何管道来轻松解决。这对我个人来说不是一个大问题,因为我无法理解为什么我需要在 $_SESSION 的可变键中放入一个|
- 只是对此感到好奇。
这是一个已知的错误
https://bugs.php.net/bug.php?id=33786
解决方法是更新到 5.5.4 并使用 php_serialize 会话序列化程序
使用这个 php 文件 'test3.php',我证明了两者 |(管道(和!(bang( 将导致_SESSION在 PHP 5.4 中失败,如果它们用于_SESSION键。此外,0x20 和 0x7f 之间的任何其他 ASCII 字符都不能导致它失败。 我不容易访问其他版本的PHP来经验检查它们的行为。
<?php
session_start( );
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test session keys</title>
</head>
<body>
<form method="post" target="test3.php">
<input type="submit" id="submit" name="submit" value="Submit">
<?php
echo "<br>_SESSION...<br>";
var_dump( $_SESSION );
echo "'n".'<br><input type="text" id="text" name="text" length="1" ';
if( $_SERVER[ 'REQUEST_METHOD' ] != 'POST' ) {
$t = chr( 32 );
echo 'value="&#'.ord( $t ).';">';
$_SESSION[ 'key' ] = ' ';
$str = 'first';
} else {
$str = 'good';
if( count( $_SESSION ) != 2 ) {
$str = 'BAD';
}
$_SESSION = array( );
$t = substr( $_POST[ 'text' ], 0, 1);
echo 'value="&#'.(ord($t) + 1 ).';">';
$_SESSION[ 'key' ] = chr(ord($t) + 1 );
}
echo "'n".'<br><input type="text" id="check" name="check" length="1" value="&#'.ord( $t ).';">';
echo "'n".'<br><input type="text" id="check2" name="check2" length="6" value="%'.bin2hex( $t ).'";">';
echo '<span id="success"></span>';
echo "<script> document.getElementById( 'success' ).innerHTML = '".$str."'; </script>";
$_SESSION[ "alpha".$_SESSION['key']."four" ] = 'Hello World';
?>
</form>
</body>
</html>