数据库的ACL实现

问题描述 投票:1回答:1

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

?>

所以我想我的问题是:

  1. SELECT查询是否足够? 还是应该使用INNER JOIN来达到相同的结果? (有关系吗?)
  2. 查询成功后,如何根据级别显示页面? 例如,如果返回了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

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

这有实际意义吗?

php mysql sql database acl
1个回答
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'] firstime进行重定向。

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

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

确保在include之前执行session_start()

本质上这将非常简单

© www.soinside.com 2019 - 2024. All rights reserved.