我开发了一个PHP会话类,并使用一些示例对其进行了测试(参见下面的源代码)。看起来没问题。现在我想让这个会议以某种方式“安全”。我找到了一些用于加密cookie的示例代码(在Courioso的书籍Expert PHP和MySQL中)。这是代码片段。
加密Cookie代码
$cookieData = serialize($user);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
srand();
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encryptedData = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $secret,
$cookieData, MCRYPT_MODE_CBC, $iv);
setcookie('user', base64_encode).':'.$iv);
和用于解密cookie的类似代码
我的第一个问题是:我能相信这段代码吗?即它真的安全吗? (我尝试了那本书的其他一些代码示例,发现它们相当错误。)
我不完全理解如何将加密cookie的代码嵌入到我的会话类中(上面的代码 - 或任何其他cookie加密代码)。我应该替换由PHP自动生成的cookie(PHPSESSID),还是应该生成一个新cookie并加密这个自定义cookie? (我的猜测是第二个是真的,但我想确定)。
如何通过加密Cookie保护工作?我想象以下攻击: (1)如果攻击者以某种方式得到他手中的cookie,他只回复相同的cookie。好的。他没有密码,但他有加密密码。后来我只检查加密密码是否正常。因此,如果攻击者拥有cookie:游戏结束 - 无论cookie是否包含密码或“仅”加密密码。正确? (2)好的,这个问题可以使用像SSL那样的加密传输来解决。但后来我想如果我使用SLL比传输无论如何都要加密。我不需要使用加密功能再次密码密码。正确的吗?
以下是我已经使用的会话类的代码。
由于
<?php
class SessionClass {
private static $_instance;
public static function getInstance()
{
if (!(self::$_instance instanceof self))
{
self::$_instance = new self();
}
return self::$_instance;
} // getInstance
public function __construct()
{
session_set_save_handler(
array($this, "open"), array($this, "close"),
array($this, "read"), array($this, "write"),
array($this, "destroy"), array($this, "gc")
);
$createTable = "CREATE TABLE IF NOT EXISTS `session`( ".
"`sessionID` VARCHAR(128), ".
"`data` MEDIUMBLOB, ".
"`timestamp` INT, ".
"`ip` VARCHAR(15), ".
"PRIMARY KEY (`sessionID` ), ".
"KEY (`timestamp`, `sessionID`))";
mysql_query($createTable);
} // construct
public function __destruct() {
session_write_close();
}
public function open ($path, $id) {
// do nothing
return (true);
}
public function close() {
// do nothing
return (true);
}
public function read($id)
{
$escapedID = mysql_escape_string($id);
$query = sprintf("SELECT * FROM session WHERE sessionID = '%s'", $escapedID);
$res = mysql_query($query);
if ((!$res) || (!mysql_num_rows($res))) {
$timestamp = time();
$query = sprintf("INSERT INTO session (sessionID, timestamp) VALUES ('%s', %s)", $escapedID, $timestamp);
mysql_query($query);
return '';
} elseif (($row = mysql_fetch_assoc($res))) {
$query = "UPDATE session SET timestamp = ";
$query .= time();
$query .= sprintf (" WHERE sessionID = '%s'", $escapedID);
mysql_query($query);
return $row['data'];
} // elseif
return "";
} // read
public function write($id, $data)
{
$query = "REPLACE INTO session (sessionID, data, ip, timestamp) ";
$query .= sprintf("VALUES ('%s', '%s', '%s', %s)",
mysql_escape_string($id), mysql_escape_string($data),
$_SERVER['REMOTE_ADDR'], time());
mysql_query($query);
return (true);
} // write
public function destroy($id)
{
$escapedID = mysql_escape_string($id);
$query = sprintf("DELETE FROM session WHERE sessionID = %s", $escapedID);
$res = mysql_query($query);
return (mysql_affected_rows($res) == 1);
} // destroy
public function gc($lifetime)
{
$query = "DELETE FROM session WHERE ";
$query = sprintf("%s - timestamp > %s", time(), $lifetime);
mysql_query($query);
return (true);
} // gc
} // SessionClass
答案 0 :(得分:2)
使用会话的原因是不会在客户端存储敏感数据,而是将其保留在服务器端。与此数据的唯一连接是会话ID,有希望定期更改,并且每次身份验证和授权更改。
如果您现在想要在客户端存储该数据(无论采用何种形式或表示形式),您将执行与要用于的会话相反的操作。所以不要这样做,并将敏感数据保存在服务器端。
答案 1 :(得分:1)
如果我可以偏离原来的问题。您应该不将密码存储在cookie中。 Cookie存储在客户端。无论加密是什么,一个更安全的选择是在会话中保存您的用户身份验证详细信息,只需将令牌存储在客户端cookie上,该cookie将调用相应的会话。