Php 数据库的ACL实现
我正在尝试在数据库中实现ACL。我有一个数据库,看起来像:Php 数据库的ACL实现,php,mysql,sql,database,acl,Php,Mysql,Sql,Database,Acl,我正在尝试在数据库中实现ACL。我有一个数据库,看起来像: SYS_USERS { id, name, .. } AUTH { au_id, au_name, .. } USER_GROUPS { sys_users_id, auth_id } // bridge table au_id au_name ... 1 admin ... 2 staff ... ... ... ... id
SYS_USERS { id, name, .. }
AUTH { au_id, au_name, .. }
USER_GROUPS { sys_users_id, auth_id } // bridge table
au_id au_name ...
1 admin ...
2 staff ...
... ... ...
id page_name
1 admin_page.php
2 members_page.php
然后说AUTH
数据如下所示:
SYS_USERS { id, name, .. }
AUTH { au_id, au_name, .. }
USER_GROUPS { sys_users_id, auth_id } // bridge table
au_id au_name ...
1 admin ...
2 staff ...
... ... ...
id page_name
1 admin_page.php
2 members_page.php
我的问题是,如何从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';
}
但这似乎相当“硬编码”,即如果我们要扩展系统以获得更多的AUTH
角色,我们需要在上面添加更多的if/ELSEIF
语句
有人能把我引向正确的方向吗
谢谢
编辑所以我在想一种新的方法。我可以再添加两个数据库表:
PAGES { id, page_name .. }
AUTH_PAGES { au_id, pages_id, .. } // bridge between auth and pages
然后,在页面
中,我可以存储页面名称
,其中包含查看该页面所需的身份验证级别
例如:名为
admin\u page.php
的页面只能由管理员访问。因此,页面中的这一行看起来像:
SYS_USERS { id, name, .. }
AUTH { au_id, au_name, .. }
USER_GROUPS { sys_users_id, auth_id } // bridge table
au_id au_name ...
1 admin ...
2 staff ...
... ... ...
id page_name
1 admin_page.php
2 members_page.php
和验证页面
:
au_id pages_id
1 1
1 2
也就是说,auth
行admin
(au\u名称)可以访问admin\u page.php
和members\u page.php
。然后,我在PHP
中需要做的就是使用echobasename($_SERVER['PHP_SELF')将pages
表中的id
与auth_pages
表交叉引用页面名称代码>
这有什么实际意义吗?既然你提到了这将很简单,所以我可以给你提个建议
登录时获取用户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}
$_SESSION['au_name'] = {auth name from the above query} ;
现在执行上述查询并获取au\u名称
,并将其作为存储在会话变量中
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}
$_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
}
现在,在登录后第一次根据$\u会话['au\u name']
执行重定向
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
}
现在,如果用户热链接URL,即非管理员用户尝试访问页面,该怎么办。为此,创建一个名为的文件check_access.php
,并将其添加到除登录页面以外的所有页面中。
在此页面中,使用PHP获取URL并从URL获取文件名,然后检查数组$\u会话['page\u access']
中是否存在该文件名,以及是否允许用户查看页面else show消息
确保在包含之前执行session\u start()
这在本质上相当简单实现类似ZEND ACL的登录机制有点棘手。。那么,您是否保留了表中不同角色可以访问的页面列表?目前没有。这是一个更好的方法吗?我计划在重定向之前使用上面的IF-ELSE
语句进行表查找,然后通过user\u id
会话变量在每个加载页面上再次验证(以防止用户简单地键入。/admin.php
进入管理页面),该变量在成功登录时设置。谢谢。我已经使用角色、模块和不同的操作实现了一些复杂的身份验证系统。你可以在这里查看它的开源代码并下载代码。这可能会对您有所帮助。谢谢您的回复@AbhikChakraborty,我已经查看了您的系统,它看起来非常复杂。对于像我这样的简单小系统来说太复杂了。因此,我想探讨不同的选择。我在想一个新的方法,你能在编辑后看一下原始的帖子并告诉我你的想法吗?谢谢@AbhikChakraborty。对于我的系统来说,这似乎是最好的方法。但有一个问题是,有没有更直观的方法来验证页面?正如我们都提到过使用url中的文件名(即admin\u page.php
),如果我们将文件名改为admin\u page\u one.php
,会发生什么情况?然后,我们需要更改数据库表page\u name
中的行以反映此更改。我真的看不出有什么办法。有什么想法吗?是的,这是验证文件名的一个潜在问题,如果某个文件名被更改,那么相应的数据库条目也需要更改。我的意思是我看不到任何其他的选择。一个更好的方法是为每个不同的角色(如adm_uu、sales_uu)的文件使用前缀,因此只需检查前缀,您就可以确定应该由谁访问页面。这样,您只需将前缀名称存储在表中,甚至在配置文件中存储硬代码即可。谢谢@AbhikChakraborty,我没有想到这一点,这非常直观。你帮了大忙!再次感谢。