Php 使用SessionHandlerInterface与MySQL数据库…请告知
我已经通过以下方式生成了以下代码 及 这里我使用MySQL数据库来存储和检索会话变量。这段代码运行良好。不过,如果您能指出错误并分享您对这段代码的输入,那就太好了Php 使用SessionHandlerInterface与MySQL数据库…请告知,php,security,Php,Security,我已经通过以下方式生成了以下代码 及 这里我使用MySQL数据库来存储和检索会话变量。这段代码运行良好。不过,如果您能指出错误并分享您对这段代码的输入,那就太好了 class MySessionHandler implements SessionHandlerInterface { public function open($savePath, $sessionName) { $host = 'localhost'; $user = '******';
class MySessionHandler implements SessionHandlerInterface
{
public function open($savePath, $sessionName)
{
$host = 'localhost';
$user = '******';
$pass = '******';
$name = '*******';
$mysqli = new mysqli($host, $user, $pass, $name);
$this->db = $mysqli;
return true;
}
public function close()
{
return true;
}
public function read($id)
{
if(!isset($this->read_stmt)) {
$this->read_stmt = $this->db->prepare("SELECT data FROM sessions WHERE id = ? LIMIT 1");
}
$this->read_stmt->bind_param('s', $id);
$this->read_stmt->execute();
$this->read_stmt->store_result();
$this->read_stmt->bind_result($data);
$this->read_stmt->fetch();
$key = $this->getkey($id);
$data = $this->decrypt($data, $key);
return $data;
}
public function write($id, $data)
{
// Get unique key
$key = $this->getkey($id);
// Encrypt the data
$data = $this->encrypt($data, $key);
$time = time();
if(!isset($this->w_stmt)) {
$this->w_stmt = $this->db->prepare("REPLACE INTO sessions (id, set_time, data, session_key) VALUES (?, ?, ?, ?)");
}
$this->w_stmt->bind_param('siss', $id, $time, $data, $key);
$this->w_stmt->execute();
return true;
}
public function destroy($id)
{
if(!isset($this->delete_stmt)) {
$this->delete_stmt = $this->db->prepare("DELETE FROM sessions WHERE id = ?");
}
$this->delete_stmt->bind_param('s', $id);
$this->delete_stmt->execute();
return true;
}
public function gc($maxlifetime)
{
if(!isset($this->gc_stmt)) {
$this->gc_stmt = $this->db->prepare("DELETE FROM sessions WHERE set_time < ?");
}
$old = time() - $max;
$this->gc_stmt->bind_param('s', $old);
$this->gc_stmt->execute();
return true;
}
private function getkey($id) {
if(!isset($this->key_stmt)) {
$this->key_stmt = $this->db->prepare("SELECT session_key FROM sessions WHERE id = ? LIMIT 1");
}
$this->key_stmt->bind_param('s', $id);
$this->key_stmt->execute();
$this->key_stmt->store_result();
if($this->key_stmt->num_rows == 1) {
$this->key_stmt->bind_result($key);
$this->key_stmt->fetch();
return $key;
} else {
$random_key = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
return $random_key;
}
}
private function encrypt($data, $key) {
$salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
$key = substr(hash('sha256', $salt.$key.$salt), 0, 32);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_ECB, $iv));
return $encrypted;
}
private function decrypt($data, $key) {
$salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
$key = substr(hash('sha256', $salt.$key.$salt), 0, 32);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($data), MCRYPT_MODE_ECB, $iv);
return $decrypted;
}
}
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
类MySessionHandler实现SessionHandlerInterface
{
公用函数打开($savePath,$sessionName)
{
$host='localhost';
$user='*****';
$pass='*****';
$name='********';
$mysqli=newmysqli($host、$user、$pass、$name);
$this->db=$mysqli;
返回true;
}
公共功能关闭()
{
返回true;
}
公共函数读取($id)
{
如果(!isset($this->read stmt)){
$this->read_stmt=$this->db->prepare(“从id=限制1的会话中选择数据”);
}
$this->read_stmt->bind_param('s',$id);
$this->read_stmt->execute();
$this->read_stmt->store_result();
$this->read\u stmt->bind\u result($data);
$this->read_stmt->fetch();
$key=$this->getkey($id);
$data=$this->decrypt($data,$key);
返回$data;
}
公共函数写入($id$data)
{
//获取唯一密钥
$key=$this->getkey($id);
//加密数据
$data=$this->encrypt($data,$key);
$time=time();
如果(!isset($this->w_stmt)){
$this->w_stmt=$this->db->prepare(“替换为会话(id、设置时间、数据、会话密钥)值(?、、?)”;
}
$this->w_stmt->bind_param('siss',$id,$time,$data,$key);
$this->w_stmt->execute();
返回true;
}
公共功能销毁($id)
{
如果(!isset($this->delete_stmt)){
$this->delete_stmt=$this->db->prepare(“从id=?”的会话中删除”);
}
$this->delete_stmt->bind_param('s',$id);
$this->delete_stmt->execute();
返回true;
}
公共函数gc($maxlifetime)
{
如果(!isset($this->gc_stmt)){
$this->gc\u stmt=$this->db->prepare(“从设置时间的会话中删除”);
}
$old=time()-$max;
$this->gc_stmt->bind_param('s',$old);
$this->gc_stmt->execute();
返回true;
}
私有函数getkey($id){
如果(!isset($this->key stmt)){
$this->key_stmt=$this->db->prepare(“从id=?限制1的会话中选择会话密钥”);
}
$this->key\u stmt->bind\u param('s',$id);
$this->key_stmt->execute();
$this->key\u stmt->store\u result();
如果($this->key\u stmt->num\u rows==1){
$this->key\u stmt->bind\u result($key);
$this->key_stmt->fetch();
返回$key;
}否则{
$random_key=hash('sha512',uniqid(mt_rand(1,mt_getrandmax()),true));
返回$random_键;
}
}
私有函数加密($data,$key){
$salt='cH!swe!retregu7w6bedrup7usudu2hege*ewr4n39=E@rAsp7c-Ph@pH';
$key=substr(散列('sha256',$salt.$key.$salt),0,32);
$iv_size=mcrypt_get_iv_size(mcrypt_RIJNDAEL_256,mcrypt_MODE_ECB);
$iv=mcrypt\u create\u iv($iv\u大小,mcrypt\u兰德);
$encrypted=base64_encode(mcrypt_encrypt(mcrypt_RIJNDAEL_256,$key,$data,mcrypt_MODE_ECB,$iv));
返回$encrypted;
}
私有函数解密($data,$key){
$salt='cH!swe!retregu7w6bedrup7usudu2hege*ewr4n39=E@rAsp7c-Ph@pH';
$key=substr(散列('sha256',$salt.$key.$salt),0,32);
$iv_size=mcrypt_get_iv_size(mcrypt_RIJNDAEL_256,mcrypt_MODE_ECB);
$iv=mcrypt\u create\u iv($iv\u大小,mcrypt\u兰德);
$decrypted=mcrypt_decrypt(mcrypt_RIJNDAEL_256,$key,base64_decode($data),mcrypt_MODE_ECB,$iv);
返回$decrypted;
}
}
$handler=新的MySessionHandler();
会话设置保存处理程序($handler,true);
会话_start();
谢谢你的时间
干杯您没有锁定会话。这是最大的错误 每当PHP中的请求启动会话并从文件中读取数据时,PHP就会获取该文件的锁,任何并行请求都会停止并等待
session\u start()
函数,直到释放锁为止
如果不锁定,将发生以下情况:第一个请求读取数据库中的所有数据。第二个请求也读取相同的数据。第一个请求将一个值更改为a。第二个请求将另一个值更改为B。第一个请求结束并将其a写回数据库。然后第二个请求用B写回更改,但没有A。数据丢失
我注意到的另一件事是:为什么要用base64对加密数据进行编码?这不是必需的,数据库可以接受二进制数据。这样做的唯一好处是,您的主人可以卖给您一台更大的机器。谢谢斯文……非常好的投入。我不知道如何在php中锁定。我会更新代码。