数据库的ACL实现

时间:2014-05-01 06:08:30

标签: php mysql sql database acl

我试图在我的数据库中实现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';
}                  

&GT;

所以我想我的问题是:

  1. SELECT查询是否足够?或者我应该使用INNER JOIN来获得相同的结果? (这有关系吗?)
  2. 查询成功后,如何根据级别显示页面?例如,如果它返回admin,我是否写了一个函数

  3. if ($result == 'admin') {
          // show admin.php
        } elseif ($result == 'staff') {
          // show staff.php
        } else { ... }
    

    但这似乎很难编码&#39;,即如果我们要扩展系统以获得更多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
    

    也就是说authadmin(au_name)可以访问admin_page.phpmembers_page.php。然后,我需要在PHP id中使用pagesauth_pages表格echo basename($_SERVER['PHP_SELF']);交叉引用页面名称。

    这是否具有实际意义?

1 个答案:

答案 0 :(得分:1)

既然你提到它会变得简单,所以我建议你这样做。

在登录时获取用户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']第一次进行重定向。

现在,如果用户热链接一个URL,即非管理员用户尝试访问页面,该怎么办?因此,为此创建一个名为check_access.php的文件,并将其包含在登录页以外的所有页面中。

在此页面中,您将使用PHP获取URL并从URL获取文件名,然后检查数组$_SESSION['page_access']上是否存在该文件名,如果是,则允许用户查看其他显示消息的页面。

确保在包含之前session_start()

这本质上相当简单