我正在开发一个 Web 应用程序 list 系统,该系统涉及不同级别的用户权限和这些级别内的各个权限的微观管理。所以大多数管理员都拥有所有权限,但您可以创建一个管理员并剥夺他们的特定权限。最终,这些权限作为位串存储在 MySQL 数据库中,其中 1 表示他们有权限,0 表示他们没有。我正在努力在不牺牲安全性的情况下提高系统的效率。我不想在每次用户想要完成操作时运行数据库搜索并检查权限,而是希望在 PHP Session 变量中缓存权限以及从服务器提取这些权限的时间戳。
$query_getUser = $this->User->prepare("SELECT * FROM users WHERE Email = ?");
$query_getUser->bindParam(1, $Email);
$query_getUser->execute();
$result = $query_getUser->fetchAll(PDO::FETCH_ASSOC);
$date = new DateTime();
session_start();
$_SESSION['Email'] = $Email;
$_SESSION['Password'] = $Password;
$_SESSION['Timestamp']= $date->getTimestamp();
$_SESSION['Permissions']= $result['Permissions'];
我遇到的主要问题是在哪里存储全局变量。什么地方最安全?本质上,我想将全局当前缓存日期存储在某个地方,以便我可以在 O(1) 时间内访问它以进行比较。
此外,以这种方式实现权限是否存在任何重大问题?如果不经常修改用户权限,并且新用户在将其添加到系统之前还没有拉取权限(因此 create_user 不会导致缓存更新,但 modify_user 会),这是一种合理的方法吗?
最佳答案
对于具有普通全局变量的复杂应用程序来说会变得相当困惑。我喜欢做的是将检索/存储机制包装在一个类中,让类完成所有工作。
像这样:
class Auth {
public static function has_privilege($privilege) {
$privileges = static::_get_privileges();
if(in_array($privilege, $privileges)) {
return true;
}
return false;
}
protected static function _get_privileges() {
$from_session = $_SESSION['Privileges'];
$last_update = $_SESSION['Timestamp'];
if(time() - $last_update > 60*60*24) { // One day
// Fetch them from the DB
}
else {
return $from_session;
}
}
}
然后像这样检查权限:
if(\Auth::has_privilege('do_something')) {
echo 'You can do something.';
} else {
echo 'You cannot do something.';
}
最好将所有这些都作为 User
类的一部分,但这应该会给您一个想法。
现在,就安全性而言,这取决于您的系统。默认的 PHP session 功能将 session 信息存储在 /tmp
目录中的文件中,因此只要该目录是安全的,那么您的 session 就是安全的。您最应该担心的是 session 劫持,但这与您的权限存储问题无关。
关于用于缓存权限的 PHP 全局时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20230641/