【发布时间】:2016-08-13 16:55:24
【问题描述】:
我有两个网站,一个是 TLS,一个不是,两者都用于同一个客户端,但我需要这些网站相互(并且仅相互)共享 用户 的公共数据, 订单、账户等
这通常使用$_SESSION 数据来完成,但我显然无法在其他站点上使用这些数据,而且我发现我可以将会话数据存储在数据库 (MySQL) 中而不是文件系统中。
我已经挖掘并找到了This useful guide 以及这个较旧但 useful guide。我还发现了this guide,它的 MySQL 稍微更新一些。
我写了一个接口类,但它只是部分工作,它将会话数据存储在数据库中,但它不检索它。我也用过suggested method from the PHP manual。
My MySQL(复制自上述前几个链接):
CREATE TABLE `sessions` (
`id` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
`access` int(10) NOT NULL,
`data` text COLLATE utf8_unicode_ci NOT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDb DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
请注意: 在我向您展示我的接口类之前,请知道 Db 连接使用我自己定制的接口,并且它本身就可以完美运行。
$sessionDBconnectionUrl包含会话数据库连接详细信息,因为我将会话保存在与主要网站内容不同的数据库中。
我的界面类(基于以上所有链接)
<?php
/***
* Created by PhpStorm.
***/
class HafSessionHandler implements SessionHandler {
private $database = null;
public function __construct($sessionDBconnectionUrl){
if(!empty($sessionDBconnectionUrl) && file_exists($_SERVER['DOCUMENT_ROOT'].$sessionDBconnectionUrl)) {
require_once "class.dataBase.php";
// Instantiate new Database object
$this->database = new Database($sessionDBconnectionUrl);
}
else {
error_log("Session could not initialise class.");
}
}
/**
* Open
*/
public function open($savepath, $id){
$openRow = $this->database->getSelect("SELECT `data` FROM sessions WHERE id = ? LIMIT 1",$id);
if($this->database->selectRowsFoundCounter() == 1){
// Return True
return $openRow['data'];
}
else {
// Return False
return ' ';
}
/**
* Read
*/
public function read($id)
{
// Set query
$readRow = $this->database->getSelect('SELECT `data` FROM sessions WHERE id = ? LIMIT 1', $id,TRUE);
if ($this->database->selectRowsFoundCounter() > 0) {
return $readRow['data'];
} else {
error_log("could not read session id ".$id);
return '';
}
}
/**
* Write
*/
public function write($id, $data)
{
$access = time();
// Set query
$dataReplace[0] = $id;
$dataReplace[1] = $access;
$dataReplace[2] = $data;
if ($this->database->noReturnQuery('REPLACE INTO sessions(id,access,`data`) VALUES (?, ?, ?)', $dataReplace)) {
return TRUE;
} else {
return FALSE;
}
}
/**
* Destroy
*/
public function destroy($id)
{
// Set query
if ($this->database->noReturnQuery('DELETE * FROM sessions WHERE id = ? ', $id)) {
return TRUE;
} else {
return FALSE;
}
}
/**
* Close
*/
public function close(){
// Close the database connection
// If successful
if($this->database->dbiLink->close){
// Return True
return true;
}
// Return False
return false;
}
/**
* Garbage Collection
*/
public function gc($max)
{
// Calculate what is to be deemed old
$old = time() - $max;
// Set query
if ($this->database->noReturnQuery('DELETE * FROM sessions WHERE access < ?', $old)) {
return TRUE;
} else {
return FALSE;
}
}
public function __destruct()
{
$this->close();
}
}
我的测试页(从头开始编写!)
<?php
require "class.sessionHandler.inc.php";
$HSH = new HafSessionHandler("connection.session.dbxlink.php");
session_set_save_handler( $HSH, TRUE );
session_start();
print "<p>Hello this is an index page</p>";
$_SESSION['horses'] = "treesx3";
$_SESSION['tiespan'] = (int)$_SESSION['tiespan']+7;
print "<p>There should be some session data in the database now. <a href='index3.php'>link</a></p>";
var_dump($_SESSION);
exit;
问题:
我运行的测试页面可以将数据保存到数据库中,但它们似乎没有检索到数据,
我启用了错误日志记录并且没有报告任何 PHP 错误。没有报告严重的 MySQL 错误。
为什么它不起作用?
【问题讨论】:
-
我猜你最糟糕的问题是域之间的 cookie 共享(是的,客户端)......
-
为什么?你能再解释一下吗?
-
这两个站点将使用一个转移页面,因此从主站点对购物网站的所有访问都将通过一个转移页面,该页面在将用户传递到他们的目标页面之前设置会话数据转移。
-
请看,会话密钥存储在浏览器上的 cookie 中,因此站点知道它是同一个访问者(cookie 在每个请求中发送),但是它们被域沙盒化。如果
http://mywebsite.com/尝试访问您的http://google.com/cookie,这是被禁止的并且存在安全漏洞(有人可能会窃取您的 gmail 会话)。 -
这就是为什么这没有发生,两个站点都引用存储在数据库中的会话。因此,通过从一个站点传递到另一个站点的识别标记,所有数据都可以在 new 会话 cookie 中检索。
标签: php mysql database session