通过 PHP 登录到 MySQL 数据库帐户,同时实施行级安全性

Logging Into MySQL database account through PHP while implementing row-level security

我正处在我正在从事的项目中,由于在 MySQL 中信息太多而经验不足,我想得太多了,所以我非常想寻找这里的专家说 "shut up and do this." 我什至愿意接受有人说我的整个方法很愚蠢,应该彻底改革的建议。该项目中唯一不可协商的是 php 和 MySQL.

的使用

所以我正在尝试在 MySQL 中实现行级安全性。阅读一些解释 MySQL 没有角色的好文章,因此您需要为每个需要 FGAC 的 table 使用视图,或者在条件过滤用户可识别信息(如用户 ID)的情况下使用视图。由于数据库的相对复杂性和数据库性质的安全考虑,我选择了查看路线。这是我的视图示例:

create OR replace view v_system_requirement (
 sys_id,
 req_id, 
 sysreq_notes,
 rate_id,
 range_id,
 art_id,
)
as
select
  system_requirement.org_id,
  organization.org_name,
  organization.org_parent_branch,
  system.sys_id,
  system.sys_name
from organization JOIN system USING (org_id)
where
  organization.org_id IN 
    (select o.org_id from organization o JOIN user u ON o.org_parent_branch=u.org_id OR o.org_id=u.org_id WHERE u.user_email=substring_index(user(), '@', 2)
);

select * from v_user_reference;

由于每个用户都有自己的数据库帐户,其中绝大多数只能select、更新、插入等相关视图,这完美地给出了用户工作的组织对于用户组织的直接子组织,以及属于上述任何组织的任何系统。用户名是他们的电子邮件地址,因此是用户函数 substring_index 中的 2,他们的密码经过充分哈希处理。

当我添加网络界面时,问题就来了。显然,当用户使用他们的用户名和密码登录时,这些将通过 mysqli_connect() 传递给数据库。据我所知,最佳做法是在每个事务或事务组 运行 后关闭连接。

那么问题就变成了,用户如何在他的数据库账户下进行连接呢?我显然不会每次都要求他重新输入密码。将散列密码保存在 $_SESSION 变量中不是一个好主意,对吧?鉴于此,是否可以在 MySQL 端做一些事情来连接为更通用的帐户,但将用户设置为他自己,这样 user() 将 return 他的实际数据库帐户名称?

或者,正如我在开头所问的那样,这种方法是否只是愚蠢的,应该被废弃以支持更好的做法?感谢您提供任何信息。

通常在 PHP/MySQL 应用程序中,应用程序 有一个单独的帐户来访问数据库。这将存储在某种配置文件中或您创建数据库连接的 class 中。

然后您可以将用户的数据存储在 users table 中,您还可以将 roles/permissions table 加入到每个用户通过 user_permissions/user_roles table.

这样您就可以让用户登录并通过将他们的凭据与他们在数据库中的行进行匹配来进行身份验证,并且您可以管理他们拥有的权限,而不必担心他们一直输入密码是时候登录数据库了,因为应用程序登录数据库而不是用户。

使用 W3Schools 教程作为基础,它看起来像这样:

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// prepare and bind
$stmt = $conn->prepare("SELECT * FROM users WHERE email = ?");
$stmt->bind_param("s", $_POST['email']);
$stmt->execute();

$user = $stmt->fetch_assoc();

if(password_verify($_POST['password'], $user['password']))
{
    echo "User authenticated";
}
else 
{
    echo "DENIED!!";
}

?>

然后您可以将您的用户已通过身份验证的事实存储在 $_SESSION 变量中,并让您的应用程序代码检查该变量以查看是否应允许用户留在 "dashboard"或被重定向回登录页面。