PHP安全-會(huì)話數(shù)據(jù)暴露(二)
當(dāng)你關(guān)注于防止源碼的暴露時(shí),你的會(huì)話數(shù)據(jù)只同樣存在著風(fēng)險(xiǎn)。在默認(rèn)情況下,SESSION保存在/tmp目錄下。這樣做在很多情形下是很方便的,其中之一是所有用戶都有對(duì)/tmp的寫入權(quán)限,這樣Apache同樣也有權(quán)限進(jìn)行寫入。雖然其他用戶不能直接從shell環(huán)境讀取這些會(huì)話文件,但他們可以寫一個(gè)簡單的腳本來進(jìn)行讀取:
<?php
header(’Content-Type: text/plain’);
session_start();
$path = ini_get(’session.save_path’);
$handle = dir($path);
while ($filename = $handle->read())
{
if (substr($filename, 0, 5) == ’sess_’)
{
$data = file_get_contents('$path/$filename');
if (!empty($data))
{
session_decode($data);
$session = $_SESSION;
$_SESSION = array();
echo 'Session [' . substr($filename, 5) . ']n';
print_r($session);
echo 'n--nn';
}
}
}
?>
這個(gè)腳本在session.save_path所定義的會(huì)話文件保存目錄中搜索以sess_為前綴的文件。找到文件后,即對(duì)它的內(nèi)容進(jìn)行解析并用print_r()函數(shù)顯示它的內(nèi)容。這樣其它開發(fā)者就容易地取得了你的用戶的會(huì)話數(shù)據(jù)。
解決這個(gè)問題的最好方法是把你的會(huì)話數(shù)據(jù)存入用用戶名和密碼保護(hù)的數(shù)據(jù)庫中。由于數(shù)據(jù)庫的訪問是受控的,這樣就多了一層額外的保護(hù)。通過應(yīng)用前節(jié)中提及的技巧,數(shù)據(jù)庫可以為你的敏感數(shù)據(jù)提供一個(gè)安全的存放地,同時(shí)你應(yīng)該保持警惕,你的數(shù)據(jù)庫安全性正變得越來越重要。
為在數(shù)據(jù)庫中保存會(huì)話數(shù)據(jù),首先需要建立一個(gè)數(shù)據(jù)表:
CREATE TABLE sessions
(
id varchar(32) NOT NULL,
access int(10) unsigned,
data text,
PRIMARY KEY (id)
);
如果你使用的是MySQL,則表結(jié)構(gòu)描述如下:
mysql> DESCRIBE sessions;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | varchar(32) | | PRI | | |
| access | int(10) unsigned | YES | | NULL | |
| data | text | YES | | NULL | |
+--------+------------------+------+-----+---------+-------+
如要使會(huì)話數(shù)據(jù)能保存在此表中,你需要使用session_set_save_handler( )函數(shù)來編輯PHP的內(nèi)建會(huì)話機(jī)制:
<?php
session_set_save_handler(’_open’,
’_close’,
’_read’,
’_write’,
’_destroy’,
’_clean’);
?>
Each of these six arguments is the name of a function that you must write. These functions handle the following tasks:
以上的六個(gè)參數(shù)每一個(gè)都代表著需要你編寫的函數(shù)的名稱,他們對(duì)下面的任務(wù)進(jìn)行處理:
l打開會(huì)話存儲(chǔ)
l關(guān)閉會(huì)話存儲(chǔ)
l讀取會(huì)話數(shù)據(jù)
l寫入會(huì)話數(shù)據(jù)
l消滅會(huì)話數(shù)據(jù)
l清除舊會(huì)話數(shù)據(jù)
我有意使用了有意義的名稱,這樣你可以一下看出它們的目的。命名是任意的,但你可能希望用下劃線開頭(如此處所示)或其它的命名約定來防止名稱沖突。下面是這些函數(shù)(使用MySQL)的示例:
<?php
function _open()
{
global $_sess_db;
$db_user = $_SERVER[’DB_USER’];
$db_pass = $_SERVER[’DB_PASS’];
$db_host = ’localhost’;
if ($_sess_db = mysql_connect($db_host, $db_user, $db_pass))
{
return mysql_select_db(’sessions’, $_sess_db);
}
return FALSE;
}
function _close()
{
global $_sess_db;
return mysql_close($_sess_db);
}
function _read($id)
{
global $_sess_db;
$id = mysql_real_escape_string($id);
$sql = 'SELECT data
FROM sessions
WHERE id = ’$id’';
if ($result = mysql_query($sql, $_sess_db))
{
if (mysql_num_rows($result))
{
$record = mysql_fetch_assoc($result);
return $record[’data’];
}
}
return ’’;
}
function _write($id, $data)
{
global $_sess_db;
$access = time();
$id = mysql_real_escape_string($id);
$access = mysql_real_escape_string($access);
$data = mysql_real_escape_string($data);
$sql = 'REPLACE
INTO sessions
VALUES (’$id’, ’$access’, ’$data’)';
return mysql_query($sql, $_sess_db);
}
function _destroy($id)
{
global $_sess_db;
$id = mysql_real_escape_string($id);
$sql = 'DELETE
FROM sessions
WHERE id = ’$id’';
return mysql_query($sql, $_sess_db);
}
function _clean($max)
{
global $_sess_db;
$old = time() - $max;
$old = mysql_real_escape_string($old);
$sql = 'DELETE
FROM sessions
WHERE access < ’$old’';
return mysql_query($sql, $_sess_db);
}
?>
你必須要在session_start( )之前調(diào)用session_set_save_handler( )函數(shù),但你可以在任何地方對(duì)這些函數(shù)本身進(jìn)行定義。
這個(gè)流程的漂亮之處在于你無須對(duì)代碼進(jìn)行編輯或變化使用會(huì)話的方式。$_SESSION依然存在,行為依舊,還是由PHP來產(chǎn)生與傳遞會(huì)識(shí)標(biāo)識(shí),對(duì)有關(guān)會(huì)話的配置變更同樣還會(huì)生效。所有你需要做的只是調(diào)用這一個(gè)函數(shù)(同時(shí)建立由它指定的所有函數(shù)),PHP就會(huì)照顧余下的事情。
相關(guān)文章:
1. JavaEE SpringMyBatis是什么? 它和Hibernate的區(qū)別及如何配置MyBatis2. android 控件同時(shí)監(jiān)聽單擊和雙擊實(shí)例3. Python 忽略文件名編碼的方法4. 解決vue頁面刷新,數(shù)據(jù)丟失的問題5. Java Media Framework 基礎(chǔ)教程6. springboot項(xiàng)目整合druid數(shù)據(jù)庫連接池的實(shí)現(xiàn)7. python 讀txt文件,按‘,’分割每行數(shù)據(jù)操作8. android studio實(shí)現(xiàn)簡單的計(jì)算器(無bug)9. 在Mac中配置Python虛擬環(huán)境過程解析10. Python趣味挑戰(zhàn)之用pygame實(shí)現(xiàn)簡單的金幣旋轉(zhuǎn)效果
