【发布时间】:2014-10-07 14:15:43
【问题描述】:
我将会话存储在数据库中,我想在用户注销时删除所有会话行作为安全预防措施(以防他们在多台计算机上登录)。
我的sessions 表如下所示:
id | access | data
mj6u4v5rs3hqbo18o5p3ip9h45 2014-08-14 02:47:02 user_id|i:1;fb_123412341234_user_id|s:11:"12341243";.....
如果用户在多台计算机上登录,那么数据库中将有多行。我可以看到将行与用户关联的唯一方法是 data 列中的 user_id 变量。
我的问题是,如何删除与特定用户 ID 关联的所有行?
这里是会话类:
namespace app;
class Session {
/** @var \PDO */
private $db;
function __construct(\PDO $db) {
$this->db = $db;
session_set_save_handler(
array($this, '_open'),
array($this, '_close'),
array($this, '_read'),
array($this, '_write'),
array($this, '_destroy'),
array($this, '_gc')
);
session_start();
}
public function test() {
return 'hey';
}
public function _open() {
return true;
}
public function _close() {
return true;
}
public function _read($id) {
$stmt = $this->db->prepare('SELECT data FROM sessions WHERE id = :id');
makeQuery($stmt, array(':id' => $id));
$sRow = $stmt->fetch(\PDO::FETCH_ASSOC);
if (!empty($sRow)) {
return $sRow['data'];
}
else {
return '';
}
}
public function _write($id, $data) {
$stmt = $this->db->prepare('REPLACE INTO sessions VALUES (:id, UTC_TIMESTAMP(), :data)');
makeQuery($stmt, array(':id' => $id, ':data' => $data));
return true;
}
public function _destroy($id) {
$stmt = $this->db->prepare('DELETE FROM sessions WHERE id = :id');
makeQuery($stmt, array(':id' => $id));
return true;
}
public function _gc($maxLifetimeTimestamp) {
$maxLifetime = date('Y-m-d H:i:s', $maxLifetimeTimestamp);
$stmt = $this->db->prepare('DELETE FROM sessions WHERE (UTC_TIMESTAMP() - access) > :maxLifetime'); // @todo test this to ensure math is correct
makeQuery($stmt, array(':maxLifetime' => $maxLifetime));
return true;
}
}
【问题讨论】:
-
“我的问题是,如何删除与特定用户 ID 关联的所有行?” - 你不是用
DELETE FROM sessions WHERE id = :id做的吗? -
@Fred-ii- 不,删除是数据库中的特定行。如果用户在多台计算机上登录,那么数据库中将有多行供他们使用(每行都有唯一的 ID)。所以行 ID 和用户 ID 没有任何关系,用户 ID 是作为会话数据存储的。
-
@Nate 好的,那么这些记录之间的共同点是什么?找到它,然后用它来删除您的数据。 编辑: 刚刚看到你的帖子。非结构化数据总是会让这类任务变得棘手。您可能必须使用例如为您的删除创建自定义条件子字符串 0, 10 ==
user_id|i:然后是它的位置,直到分号与您的用户 ID 匹配 -
@scrowler 共同点是
data列中的user_id值。但是data列中的数据是序列化的,所以我不能简单地查询delete from sessions where user_id = 1。我也许可以进行全文搜索,但我认为可能有更好的方法。