Authorisatie
Ik heb een authorisatiescript. Deze ziet er als volgt uit:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?PHP
/* USER LEVELS */
$ulNamen = array(0 => 'Normale gebruiker',
1 => 'Teameditor',
2 => 'Nieuwsredacteur',
4 => 'Contentbeheerder',
8 => 'Administrator');
define("GEBRUIKER", 0 );
define("TEAMS", 1 );
define("REDACTIE", 2 );
define("CONTENT", 4 );
define("ADMIN", 8);
/* LEVEL AREAS */
define("ADMIN_PANEL", TEAMS + CONTENT + REDACTIE + ADMIN);
define("NEWS", REDACTIE + ADMIN);
define("LINKS", ADMIN);
define("TEAM", TEAMS + ADMIN);
define("PAGE", CONTENT + ADMIN);
define("USER", ADMIN);
define("BANNER", ADMIN);
define("ANNOUNCE", ADMIN);
define("SETTINGS", ADMIN);
// Functie
function isUserAuthorized( $sectionlevel )
{
// controleer of de sessie gegevens aanwezig zijn
if( !isset( $_SESSION["USER"]["LEVEL"] ) )
{
// de sessie gegevens zijn niet aanwezig
return false;
}
// haal het gebruikersniveau op (in integer formaat)
$userlevel = intval( $_SESSION["USER"]["LEVEL"] );
// ok, hier gebeurd de werkelijke magic ;-) We gebruiken de bitwise AND operator!
// controleer of de gebruiker toegang heeft tot de sectie
return ( $userlevel & $sectionlevel ) > 0 ;
}
// Voorbeeld
if(!isUserAuthorized(NEWS))
{
header("Location: admin.php");
}
?>
/* USER LEVELS */
$ulNamen = array(0 => 'Normale gebruiker',
1 => 'Teameditor',
2 => 'Nieuwsredacteur',
4 => 'Contentbeheerder',
8 => 'Administrator');
define("GEBRUIKER", 0 );
define("TEAMS", 1 );
define("REDACTIE", 2 );
define("CONTENT", 4 );
define("ADMIN", 8);
/* LEVEL AREAS */
define("ADMIN_PANEL", TEAMS + CONTENT + REDACTIE + ADMIN);
define("NEWS", REDACTIE + ADMIN);
define("LINKS", ADMIN);
define("TEAM", TEAMS + ADMIN);
define("PAGE", CONTENT + ADMIN);
define("USER", ADMIN);
define("BANNER", ADMIN);
define("ANNOUNCE", ADMIN);
define("SETTINGS", ADMIN);
// Functie
function isUserAuthorized( $sectionlevel )
{
// controleer of de sessie gegevens aanwezig zijn
if( !isset( $_SESSION["USER"]["LEVEL"] ) )
{
// de sessie gegevens zijn niet aanwezig
return false;
}
// haal het gebruikersniveau op (in integer formaat)
$userlevel = intval( $_SESSION["USER"]["LEVEL"] );
// ok, hier gebeurd de werkelijke magic ;-) We gebruiken de bitwise AND operator!
// controleer of de gebruiker toegang heeft tot de sectie
return ( $userlevel & $sectionlevel ) > 0 ;
}
// Voorbeeld
if(!isUserAuthorized(NEWS))
{
header("Location: admin.php");
}
?>
In de database staat dus bij user_level een getal (bijvoorbeeld 8 is admin). Ik zou graag per gebruiker meerdere userlevels toe willen voegen, dus zeg maar 2,4 (is dan content beheren en nieuwsberichten plaatsen). Echter, hoe moet ik dan mijn function opzetten. Ik kreeg het helaas niet voor elkaar.
Ik ging eerst user_levels exploden (zodat je een 2 en een 4 krijgt), maar verder kom ik niet echt.
Ik zit hier vast:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?
function isUserAuthorized( $sectionlevel )
{
$levels = array();
// controleer of de sessie gegevens aanwezig zijn
if( !isset( $_SESSION["USER"]["LEVEL"] ) )
{
// de sessie gegevens zijn niet aanwezig
return false;
}
// haal het gebruikersniveau op (in integer formaat)
$userlevels = explode(",",$_SESSION["USER"]["LEVEL"] );
foreach($userlevels as $id => $level)
{
if(( $level & $sectionlevel ) > 0)
{
$levels[$level] = true;
}
else
{
$levels[$level] = false;
}
}
// ok, hier gebeurd de werkelijke magic ;-) We gebruiken de bitwise AND operator!
// controleer of de gebruiker toegang heeft tot de sectie
return $levels[$level];
}
?>
function isUserAuthorized( $sectionlevel )
{
$levels = array();
// controleer of de sessie gegevens aanwezig zijn
if( !isset( $_SESSION["USER"]["LEVEL"] ) )
{
// de sessie gegevens zijn niet aanwezig
return false;
}
// haal het gebruikersniveau op (in integer formaat)
$userlevels = explode(",",$_SESSION["USER"]["LEVEL"] );
foreach($userlevels as $id => $level)
{
if(( $level & $sectionlevel ) > 0)
{
$levels[$level] = true;
}
else
{
$levels[$level] = false;
}
}
// ok, hier gebeurd de werkelijke magic ;-) We gebruiken de bitwise AND operator!
// controleer of de gebruiker toegang heeft tot de sectie
return $levels[$level];
}
?>
Gewijzigd op 21/09/2010 21:41:04 door Roeltje M
Verder zou je kunnen overwegen om af te stappen van de manier van authorisatie die je nu gebruikt en dit met behulp van de database te gaan doen. Maak een tabel met rollen voor gebruikers (admin, editor, etc) en geef alle gebruiker 1 of meerdere rollen:
users
----
id
name
etc...
roles
----
id
role
user_role
--------
id
user_id
role_id
In deze opzet kun je in de user_role tabel net zoveel rollen aan de gebruiker koppelen als je wilt. Vervolgens zou je nog een extra tabel kunnen aanmaken waarin je de acties opneemt en 1 waarin je de rechten op een bepaalde actie aan een rol koppelt.
Het grote voordeel van deze opzet is dat je veel flexibeler bent dan de manier die je nu gebruikt. Het wordt heel eenvoudig om 1 bepaald recht toe te kennen aan of te ontnemen van 1 of meerdere rollen. En dat vloeit automatisch door naar alle gebruiker die betreffende rol hebben...
Voor de koppel tabel 'user_role' is het veld id overbodig dacht ik zo..
Bedankt, zal het meenemen!
@Niels: in principe zou je ook een PK aan kunnen brengen op de combinatie (user_id, role_id), daar heb je helemaal gelijk in :-)
stel een gebruiker die TEAMS+CONTENT is heeft (binair) 0101
Deze gebruiker mag dan in het ADMIN_PANEL (want 1111) maar niet NEWS plaatsen (1010) maar wel TEAM (1001)
Dus van zodra een BIT in de user rechten overeenkomt in de vereiste rechten is hij toegelaten.
Je zal even moeten spelen met de operators.
Een snelle kijk op de manual pagina toont dat je & zult moeten gebruiken
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$user = TEAMS+CONTENT;
var_dump(
($user & TEAMS + CONTENT + REDACTIE + ADMIN) == 0, // admin panel levert true
($user & REDACTIE + ADMIN) == 0, // news levert false
($user & TEAMS + ADMIN) == 0, // team levert true
);
?>
$user = TEAMS+CONTENT;
var_dump(
($user & TEAMS + CONTENT + REDACTIE + ADMIN) == 0, // admin panel levert true
($user & REDACTIE + ADMIN) == 0, // news levert false
($user & TEAMS + ADMIN) == 0, // team levert true
);
?>
Je zou dus gewoon return ($user & $sectionlevel) == 0; kunnen doen.
Gewijzigd op 21/09/2010 21:54:26 door Hipska BE
Blanche PHP op 21/09/2010 21:34:04:
Vervolgens zou je nog een extra tabel kunnen aanmaken waarin je de acties opneemt en 1 waarin je de rechten op een bepaalde actie aan een rol koppelt.
Zou ik niet doen. De acties worden slechts door de code, niet door de content bepaald en zo creëer je een onnodige laag.
Gewijzigd op 21/09/2010 23:32:54 door Pim -
printf kan je makkelijk binaire waarden weergeven, soms wel even handig als je wilt uitvogelen of je de machten van 2 of de juiste operators nog wel goed hebt:
Let trouwens wel even op met + gebruiken bij bijv. 4 + 6. Je wilt niet optellen, je wilt dat de bits voor 4 en voor 6 allebei aanstaan, en daarvoor gebruik je bitwise-or, oftewel de pipe |.
4 (0100) + 6 (0110) = 10 (1010) (zie, bitje voor 4 staat nu uit!, dus 10 & 4 == false!)
4 (0100) | 6 (0110) = 6 (0110)
Truukje, met Let trouwens wel even op met + gebruiken bij bijv. 4 + 6. Je wilt niet optellen, je wilt dat de bits voor 4 en voor 6 allebei aanstaan, en daarvoor gebruik je bitwise-or, oftewel de pipe |.
4 (0100) + 6 (0110) = 10 (1010) (zie, bitje voor 4 staat nu uit!, dus 10 & 4 == false!)
4 (0100) | 6 (0110) = 6 (0110)
Gewijzigd op 21/09/2010 23:31:56 door Jelmer -
Zolang hij met waardes van 2^n blijft zit hij safe volgens mij..