logo    PHP - Rollebaseret adgangsstyring.




Ofte er det nødvendigt, at ikke alle potentielle brugere har adgang til alt indenfor et site / programområde. Afgrænsning i brugernes adgang styres ved at kombinere logind med brugernavn og password med rollebaseret adgangsbegrænsning.


Opgaven kan løses på flere måder. Nedenfor er beskrevet en fremgangsmåde baseret på:
- 4 tabeller i database.
- et Login-program, der er uafhængigt af omverdenen (kan derfor ikke umiddelbart blive 'fanget' i adgangsbegrænsningen).
- en funktion.
Indsættelse af kode i toppen af de sider, der kan adgangsbegrænses.
- Indsættelse af kode omkring de tekstdele, der skal adgangsbegrænses.


Omdrejningspunktet i løsningen er en rollespecifik array der placeres i $_SESSION. Den produceres af kode i login-program og funktion på basis af udtræk fra databasen og bruges af kode i hhv. toppen og spredt ud over tekstdelen af siderne.


Til sidst vil blive beskrevet, hvordan man kan lave sidevis / filvis styring i stedet for større eller mindre dele af teksten på en side.




Forarbejde.


Før etablering af arrayen og indsætning af rettigheder er der en del overvejelser og arbejde at gøre. Arbejdet er dog en iterativ process, der kan fortsætte også efter at sitet er ibrugtaget.


  1. Tabeller i DB
    Til rollebaseret adgangsstyring skal der anvendes 4 tabeller i databasen:

    brugerroller


    De enkelte tabeller - især 'bruger'-tabellen - kan situationsafhængigt udvides med flere felter, men konceptet og relationerne må ikke fraviges.

  2. Styringsmåde.
    Det skal af strukturelle hensyn afklares, om man vil anvende både Sidestyring og Tekststyring, eller om man kun vil anvende tekststyring.

  3. Roller.
    Det afklares, hvilke roller der skal være til rådighed. Det gøres ved at se på, hvilke jobs den enkelte bruger skal kunne udføre. Det kan betyde alt fra, at en bruger skal have en rolle for sig selv til, at mange brugere kan anvende samme rolle. Jo mere man fjerner sig fra den første situation, des større fordel vil der være ved at anvende rollebaseret adgangsstyring fremfor brugerbaseret adgangsstyring.
    Arbejdet kan muligvis afsluttes med en vis konsolidering med færre roller som resultat. Opbygningen af roller vil ofte være et kompromis.

  4. Rettigheder
    Med rollerne på plads skal det afklares, hvilke rettigheder og rettighedskoder, der skal være til rådighed for at kunne imødekomme rollernes behov. Ved "sidestyring" er rettighedskoden de enkelte programnavne. Til tekststyring etableres der rettighedskoder der så vidt muligt skal have så selvforklarende identer som muligt.

  5. Rolle- / rettighedsmatrice
    I et regneark eller tilsvarende opbygges en 'rolle- / rettighedsmatrice'. Roller og rettigheder indsættes som hhv. rækker og kolonner. I krydsfelterne markeres med 'x' hvilke rolle- / rettighedsrelationer adgangsstyringen skal tillade.

    brugerroller og rettigheder.

  6. "Komme-igang" grundlag.
    Rolle- / rettighedsmatricen (især roller) fastlåses.




Anvendelse af rollestyring.


Brugerne har som udgangspunkt adgang til alt på sitet, der ikke er adgangsbegrænset. Opgaven er derfor at gennemgå sitet og stille spørgsmålet


Må alle se / gøre det?.


Er svaret NEJ! for blot en enkelt bruger, skal der foretages adgangsbegrænsning ved at etablere en "Rolle / rettighed i databasen og lægge begrænsningskode omkring tekstdelen, linket dertil eller menupunktet dertil.


Det er her rolle- / rettighedsmatricen skal etableres / anvendes.


Begrænsningerne kan relatere sig til:


  • Hele sider
    Begrænsningskoden placeres omkring det link / det menupunkt, der fører til den side som ikke alle må se. Sidens filnavn kan med fordel anvendes som både rettighed_navn og rettighed_kodenavn.


    Ved "automatisk login" må der ikke foretages sidebegrænsning af "index"-siden.


  • Dele af sider
    Begrænsningskoden placeres omkring den tekst, som ikke alle må se.


Begrænsningskoden ser sådan ud i sin grundform:


<?php
if (in_array("
den relevante 'rettighed_kodenavn' fra tabellen 'rettigheder'", $_SESSION[g_rettigheder] ))
{
?>

.....
Tekst, link, menupunkt der skal adgangsstyres.
.....
<?php
}
?>


Ved indlejring i omgivende HTML-kode anvendes den således:


<?php if (in_array("login_select", $_SESSION['g_rettigheder'] )) { ?>
<li><a href='login_select.php'>linktekst</a></li>
<?php } ?>


Ved indlejring af HTML-kode i omgivende PHP-kode anvendes den således:


<?php
....
echo "<td>";
if (in_array('kategori_update', $_SESSION['g_rettigheder'] )) {
echo "<a href='kategori_update.php?kat_id=$row[kat_id]'>linktekst</a>";
}
echo "</td>";
...
?>




Database.


Arbejdet med opsætning af databasen kan nu påbegyndes (evt. kun med testdata).


Den enkelte bruger knyttes via sine stamdata til den rolle der bedst styrer vedkommendes færd på sitet.


  1. Rolle
    Etabler stamdata for de roller, der skal anvendes.

  2. Rettighed
    Etabler stamdata for de rettighedsbegrænsninger.

  3. Rolle- / Rettigheder
    Etabler de korrekte kombinationer af roller og rettigheder.

  4. Brugere
    Tilknyt den korrekte rolle til de enkelte brugere via deres stamdata.




Opbygning af array.


Rollebaseret adgangsstyring er baseret på først opbygning og derefter anvendelse af en array i en $_SESSION-variabel. Arrayen kan opbygges på tre forskellige måder alt efter situationen:

  • Auto logind
    Brugeren får automatisk adgang til nogle af sitets / programmets sider som "gæst" uden selv at logge ind.
  • Intern logind
    Brugeren foretager logind (for at komme videre ind i sitet) fra en af sitets sider der enten er fri adgang til eller adgang via auto logind.
  • Ekstern logind
    Brugeren foretager logind fra en selvstændig side, der ikke er en del af sitet. Kan f.eks. give direkte adgang til sitets administrationssystem udenom sitet.




Auto logind.


Arrayen til auto logind etableres og sættes på plads på denne måde:


Øverst på de sider på sitet brugere har "gæsteadgang" til eller i deres "side-start" kontrolleres om auto-login allerede er etableret. Kan også lægges ind i alle sider på sitet.


Det gøres med koden:


include ("includes/funktioner.php");
if (!isset ($_SESSION['g_rettigheder']))
{
$_SESSION['g_rettigheder'] = rts_opret_auth_array(4);
}


Findes der ikke en "$_SESSION['g_rettigheder']" anvendes funktionen "rts_opret_auth_array" til at etablere rettigheder for rolle 4. Det er i dette tilfælde den rolle i databasen, der styrer gæsters adgang.


Efter at funktionen har returneret arrayen "g_rettigheder" placeres denne som $_SESSION-variabel.




Funktionen "rts_opret_auth_array"


Koden til opbygning af selve arrayet er ens i alle tre situationer og er derfor etableret som en funktion:


function rts_opret_auth_array ($rolle_id)
{
global $db_link;
$arr_query = "SELECT * FROM rolle_rettighed
inner join rettighed on fk_ret_id = ret_id
WHERE fk_rolle_id = $rolle_id";
$arr_result = mysqli_query($db_link, $arr_query) or die(mysqli_error($db_link));
$arr_antal = mysqli_num_rows($arr_result);

$g_rettigheder = array();

if ($arr_antal > 0)
{
while ($arr_row = mysqli_fetch_assoc ($arr_result))
{
$g_rettigheder[$arr_row['ret_id']] = $arr_row['ret_kodenavn'];
}
return $g_rettigheder; }
}


Funktionen skal have tilført variablen $rolle_id, der indeholder rolle-id for den bruger, der er ved at logge ind. Ved tilpasning kan der anvendes et andet navn på viariablen.


Den afleverer arrayen $g_rettigheder, der indeholder brugerens 'rettighed_id' og 'rettighed_kodenavn' fra databasetabellen 'rettighed'.


Funktionen henter endvidere variablen '$db_link' som global variabel.




Intern login.


Arrayen til login fra auto login etableres og sættes på plads ved hjælp af et login program og funktionen "rts_opret_auth_array" (se ovenfor):


Login-programmet placeres i sitets rodmappe sammen med sitets øvrige sider. Der skal være adgang til det fra "auto login".

Det nedenfor beskrevne program er helt uafhængigt med egen css.


<?php
$error = "";

if (isset($_POST['submit_login']))
{
$brug_usernavn = $_POST['brug_usernavn'];
$brug_password = $_POST['brug_password'];

//Valider mod brugertabel
$query = "SELECT * FROM bruger WHERE brug_usernavn = '$brug_usernavn' AND brug_password = '$brug_password'";
$result = mysqli_query($db_link, $query) or die(mysqli_error($db_link));
$row = mysqli_fetch_assoc ($result);
$antal = mysqli_num_rows($result);
$rolle_id = $row['fk_rolle_id'];
echo "rollenummer" . $rolle_id;

// Opbyg array

if ($antal == 1) // Når hentet een bruger
{
$g_rettigheder = rts_opret_auth_array($rolle_id);

$_SESSION['g_rettigheder'] = $g_rettigheder;

header("location: index.php");
}
else //Opbyg array
{
$error = "Forkert brugernavn eller password";
}
//Opbyg array

} //POST
?>

<h1>Login til Forum.</h1>
<p><?php echo $error; ?></p>
<table>
<form method='post'>
<tr><td>Brugernavn:</td><td class="mellemrum"></td><td><input type='text' name='brug_usernavn' /></td></tr>
<tr><td>Password:</td><td></td><td><input type='password' name='brug_password' /></td></tr>
<tr><td colspan=""3"> </td></tr>
<tr><td> <input type='submit' name='submit_login' value='Log ind' /></td><td colspan="2"></td></tr>
</form>
</table>




Ekstern logind.


Ekstern logind foretages med et selvstændigt program der nok er placeret indenfor mappestrukturen i det site det skal formidle login til ikke er en del af den afprogram der skal logges ind til logind fra en selvstændig fil / selvstændigt skærmbillede


Ekstern login kan f.eks. anvendes til direkte login udefra til et administrationssystem der er samlet i en selvstændig mappestruktur indenfor det site der skal administreres.


Udover skærmbillede, der kan være udført kunstfærdigt eller så simpelt som vist her, og indlejret css-styring, består logind-programmet af 3 dele:

  • Kode til validering af brugeren mod databasen.
  • Etablering af $_SESSION-array. Det meste arbejde udføres af funktionen "rts_opret_auth_array" (se ovenfor).
  • Link til en af filerne i administrationsprogrammet (sædvanligvis index.xxx)
<?php
session_start();
ob_start();
include("../includes/db_connect.php");
include("../includes/funktioner.php");
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<meta charset="UTF-8" />
<style>
#wrapper {
background: limegreen;
width: 500px;
margin: auto;
margin-top: 120px;
padding: 20px;
}

.mellemrum{
width: 30px;
}
#knap input[type="submit"]:hover{
border: 1px solid limegreen;color:#000;
}

</style>

</head>
<body>
<div id="wrapper">
<?php
$error = "";


if (isset($_POST['submit_login']))
{
$brug_usernavn = $_POST['brug_usernavn'];
$brug_password = $_POST['brug_password'];

//Valider mod brugertabel
$query = "SELECT * FROM bruger WHERE brug_usernavn = '$brug_usernavn' AND brug_password = '$brug_password'";
$result = mysqli_query($db_link, $query) or die(mysqli_error($db_link));
$row = mysqli_fetch_assoc ($result);
$antal = mysqli_num_rows($result);
$rolle_id = $row['fk_rolle_id'];
echo "rollenummer" . $rolle_id;

// Opbyg array

if ($antal == 1) // Når hentet een bruger
{
$g_rettigheder = rts_opret_auth_array($rolle_id);

$_SESSION['g_rettigheder'] = $g_rettigheder;

header('location:index.php');
}
else //Opbyg array
{
$error = "Forkert brugernavn eller password";
}
//Opbyg array

} //POST
?>

<h1>Login til xxx system.</h1>
<p><?php echo $error; ?></p>
<table>
<form method='post'>
<tr><td>Brugernavn:</td><td class="mellemrum"></td><td><input type='text' name='brug_usernavn' /></td></tr>
<tr><td>Password:</td><td></td><td><input type='password' name='brug_password' /></td></tr>
<tr><td colspan=""3"> </td></tr>
<tr><td> <input type='submit' name='submit_login' value='Log ind' /></td><td></td><td></td></tr>
</form>

<tr><td colspan=""3"> </td></tr>
<tr><td>Bruger id</td><td>Password</td></tr>
<tr><td>Anders</td><td>Anders</td></tr>
</table>
</div>
</body>
</html>
























x
x