Reputation: 797
I'm trying to implement an ACL in my database. I have a database which looks like:
SYS_USERS { id, name, .. }
AUTH { au_id, au_name, .. }
USER_GROUPS { sys_users_id, auth_id } // bridge table
And say AUTH
data looks like:
au_id au_name ...
1 admin ...
2 staff ...
... ... ...
My question is, how can I structure my query from php
such that upon login, depending on your authentication level, you are presented different pages?
At the moment I have this, which seems a little off:
<?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';
}
?>
So I guess my questions are:
SELECT
query adequate? Or should I use an INNER JOIN
to achieve the same results? (Does it matter?)admin
do I write a function such thatif ($result == 'admin') {
// show admin.php
} elseif ($result == 'staff') {
// show staff.php
} else { ... }
But this seems rather 'hard coded', i.e. if we were to extend the system for more AUTH
roles, we would need to then add in more IF/ELSEIF
statements to the above.
Anyone able to lead me in the right direction?
Thanks.
EDIT
So I was thinking of a new way to do this. I could add two more database tables:
PAGES { id, page_name .. }
AUTH_PAGES { au_id, pages_id, .. } // bridge between auth and pages
Which then in pages
I could store page_name
which would hold the authentication level required to view that page?
For example:
a page called admin_page.php
could only be accessed by administrators. Therefore this row in pages
looks like:
id page_name
1 admin_page.php
2 members_page.php
and auth_pages
:
au_id pages_id
1 1
1 2
Which is to say the auth
row admin
(au_name) has access to admin_page.php
and members_page.php
. Then all I would need to do in my PHP
would be to cross reference the page name with the id
from pages
table with auth_pages
table using echo basename($_SERVER['PHP_SELF']);
.
Does that make any practical sense?
Upvotes: 1
Views: 1249
Reputation: 44844
Since you mentioned its going to be simple so this is what I can suggest you.
At the time of login get the user id and then run a query with the id user as
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}
Now Execute the above query and get the au_name
and store it in a session variable as
$_SESSION['au_name'] = {auth name from the above query} ;
Create a function as below and execute it after the login.
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
}
Now do the redirect based on the $_SESSION['au_name']
firstime after the login.
Now what if user hotlink an URL i.e. a non-admin user try to access a page. So for that create a file called check_access.php
and add include it to all the pages other than the login page.
In this page you get the URL using PHP and get the filename from the URL, then check if that filename exists on the array $_SESSION['page_access']
and if yes user is allowed to view the page else show message.
Make sure you do session_start()
before the include .
This will be fairly simple in nature
Upvotes: 1