我正在尝试在数据库中实现ACL。 我有一个数据库,看起来像:
SYS_USERS { id, name, .. }
AUTH { au_id, au_name, .. }
USER_GROUPS { sys_users_id, auth_id } // bridge table
并说AUTH
数据如下:
au_id au_name ...
1 admin ...
2 staff ...
... ... ...
我的问题是,如何从php
构建查询,以便登录后根据身份验证级别显示不同的页面?
目前我有这个,似乎有点偏离:
<?php
// code which verifies session variables etc here
$mysql_hostname = 'localhost';
$mysql_username = '...';
$mysql_password = '...';
$mysql_dbname = '...';
try {
/* Set up new DB object */
$db = new PDO("mysql:host=$mysql_hostname;dbname=$mysql_dbname", $mysql_username, $mysql_password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* authenticate user access level */
// username = 'blah' for question clarity
$query = $db->prepare('SELECT au_name FROM auth WHERE au_id = (SELECT auth_id FROM user_groups WHERE sys_users_id = (SELECT id FROM sys_users WHERE username="blah"))');
// do something with results..
} catch(Exception $exception) {
$message = 'We are unable to process your request. Please try again later';
}
?>
所以我想我的问题是:
SELECT
查询是否足够? 还是应该使用INNER JOIN
来达到相同的结果? (有关系吗?) admin
,我是否编写了这样一个函数 if ($result == 'admin') {
// show admin.php
} elseif ($result == 'staff') {
// show staff.php
} else { ... }
但这似乎是“硬编码”,即,如果我们要将系统扩展为更多的AUTH
角色,则需要在上面添加更多的IF/ELSEIF
语句。
有人能够引导我朝正确的方向前进吗?
谢谢。
编辑
所以我在想一种新的方法。 我可以再添加两个数据库表:
PAGES { id, page_name .. }
AUTH_PAGES { au_id, pages_id, .. } // bridge between auth and pages
那我可以在哪些pages
存储page_name
来保存查看该页面所需的身份验证级别?
例如:
只有管理员才能访问名为admin_page.php
的页面。 因此, pages
这一行看起来像:
id page_name
1 admin_page.php
2 members_page.php
和auth_pages
:
au_id pages_id
1 1
1 2
也就是说auth
行admin
(au_name)可以访问admin_page.php
和members_page.php
。 然后,我在PHP
需要做的就是使用echo basename($_SERVER['PHP_SELF']);
来交叉引用页面名称与pages
表中的id
与auth_pages
表echo basename($_SERVER['PHP_SELF']);
。
这有实际意义吗?
由于您提到的过程很简单,因此我可以建议您。
登录时获取用户ID,然后以ID用户身份运行查询
select
a.au_name,a.au_id
from USER_GROUPS ag
inner join SYS_USERS su on su.id = ag.sys_users_id
inner join AUTH a on a.au_id = ag.auth_id
where ag.sys_users_id = {id of the user retrieved after the login validation}
现在执行上面的查询并获取au_name
并将其存储在会话变量中,如下所示:
$_SESSION['au_name'] = {auth name from the above query} ;
创建如下所示的函数,并在登录后执行。
get_page_access($au_id){
run a query to get all the pages for the auth id you got from previous query
store them in an array and finally to a session variable as
$_SESSION['page_access'] = $array ;
$array will hold all the pages you retrive
}
现在,在登录后根据$_SESSION['au_name']
firstime进行重定向。
现在,如果用户热链接URL(即非管理员用户)尝试访问页面该怎么办。 因此,为此创建一个名为check_access.php
的文件,并将其添加到除登录页面以外的所有页面中。
在此页面中,您使用PHP获取URL,并从URL获取文件名,然后检查该文件名是否存在于$_SESSION['page_access']
数组中,如果允许,则允许用户查看该页面的其他显示消息。
确保在include之前执行session_start()
。
本质上这将非常简单