Anzeige
Tutorialbeschreibung

Eine kleine simple Access-Control-Klasse

Eine kleine simple Access-Control-Klasse

Mit dieser recht kleinen Klasse können wir überprüfen, ob ein User die angegebenen Rechte besitzt oder mindestens die Adminstufe hat, die angegeben wurde. Dies ist hilfreich für Browsergames o.ä. Online-Seiten, wo es mehrere Administratoren mit verschiedenen Berechtigungen geben soll.


Schritt 1: Datenbank

Als Erstes erstellen wir uns eine Datenbank (sofern noch keine vorhanden ist).

Sobald wir dann eine Datenbank haben, auf die wir zugreifen können, führen wir folgenden Befehl aus:

CREATE TABLE `users` (
 `id` int(11) unsigned NOT NULL auto_increment,
 `login` varchar(55) NOT NULL,
 `pass` varchar(55) NOT NULL,
 `admin` tinyint(2) NOT NULL default '0',
 `rights` text NOT NULL,
 PRIMARY KEY (`id`)
) Type=MyISAM;

Sobald die Tabelle existiert, führen wir noch einen Insert aus. (Damit wir gleich auch ein paar Daten haben, mit denen wir die Klasse testen können).
INSERT INTO `users` (`id`, `login`, `password`, `admin`, `rights`) VALUES
(1, 'Test Account', 'test', 1, 'a:2:{i:1;i:1;i:2;i:1;}');


Schritt 2: Übersicht der Funktionen

Fangen wir nun also mit unserer eigentlichen Klasse an. Unsere Klasse setzt sich aus insgesamt 4 Funktionen zusammen. 

  • __construct -> Direktes Laden des Users.
  • &__get -> Direkte Abfrage der Felder.
  • access_control -> Überprüft, ob der User die angegebenen Rechte besitzt.
  • check_admin -> Überprüft, ob der User das angegebene Adminlevel oder höher besitzt.

Schritt 3: Benennung der Klasse

Als Erstes müssen wir unserer Klasse einen Namen geben. Sicherlich könnten wir nun irgendeine Aneinanderreihung verschiedener Buchstaben nehmen. Allerdings ist eine korrekte und auch sinnvolle Benennung einer Klasse immer praktischer. Denn so weiß man direkt, wozu diese Klasse existiert.

Ich gebe unserer Klasse den Namen "Security".

class Security {
}


 

Schritt 4: Wir definieren unsere Konstanten

Ich habe mich in dieser Klasse dazu entschieden, meine Rechte als Konstante zu speichern. Jede Konstante erhält einen numerischen Wert. Wieso das so ist, werde ich etwas weiter unten erklären.

class Security {
	
	const ACCESS_USER_EDITOR = 1;
	const ACCESS_USER_BANNED = 2;
	const ACCESS_CHAT_COMMENTS = 3;
	const ACCESS_USER_RENAME = 4;

}

Wie wir am folgenden Codebeispiel sehen, hat jede Konstante (const) einen numerischen Wert erhalten.

(ACCESS_USER_EDITOR ist 1, ACCESS_USER_BANNED ist 2, usw.usw.)


Schritt 5: Wir erstellen unsere Variable(n)

Da wir gleich alle Daten eines Users aus der Datenbank laden werden, benötigen wir noch eine Variable, die diese Daten auch speichert (damit wir diese später in der Funktion &__get() verwenden können).

class Security {
	
	const ACCESS_USER_EDITOR = 1;
	const ACCESS_USER_BANNED = 2;
	const ACCESS_CHAT_COMMENTS = 3;
	const ACCESS_USER_RENAME = 4;

var $data = array();

}


Schritt 6: Wir erstellen die Funktion "__construct"

Da wir den User automatisch ohne eine zweite Funktion aus der Datenbank laden wollen, definieren wir die Funktion __construct. Diese Funktion wird immer automatisch aufgerufen, wenn unsere Klasse gebraucht wird.

class Security {
	
	const ACCESS_USER_EDITOR = 1;
	const ACCESS_USER_BANNED = 2;
	const ACCESS_CHAT_COMMENTS = 3;
	const ACCESS_USER_RENAME = 4;
	
	var $data = array();
	
	public function __construct( $id ) {
		
		if( !empty($id) ) {
			
			$query = mysql_query('SELECT * FROM users WHERE id='.$id);
			
			if( mysql_num_rows($query) == 1 ) {
				
				$this->data = mysql_fetch_assoc($query);
			
			} else {
				
				echo 'Konnte den angegebenen User nicht laden.';
				return;
			
			}
		
		} else {
			
			echo 'Ohne Benutzer ID kann ich leider nichts aus der Datenbank laden, sorry.';
			return;
		
		}
	
	}

}

Eine kurze Erklärung dazu, was ich gerade gemacht habe:

Ich überprüfe mittels empty, ob die Variable $id leer ist; wenn diese leer ist, wird die Funktion mittels return; abgebrochen. Sollte die Variable $id allerdings einen Wert enthalten, versuche ich mittels der Funktion mysql_query, einen User (der diese ID besitzt) aus der Datenbank zu laden.

Nun prüfe ich noch mit der Funktion mysql_num_rows, ob das Laden des Users erfolgreich war oder nicht. Sollte das Laden erfolgreich gewesen sein, übergebe ich die Daten mittels mysql_fetch_assoc an unsere Variable $data. ($this->data). Sollte das Laden allerdings fehlschlagen, wird auch hier wieder die Funktion mittels return; abgebrochen.


Schritt 7: Definition von &__get

Da wir gleich ein paar Daten aus der Variable $data benötigen und ich nicht unbedingt immer $this->data[$field] schreiben möchte, definiere ich noch eine Funktion, die es mir erlaubt, die Abfrage etwas zu verkürzen.

	public function &__get( $field ) {
		
		return $this->data[$field];
	
	}

Nun brauche ich einfach nur noch $this->$field einzugeben, und mir wird der Wert dieses Feldes ausgegeben.


Schritt 8: Wir definieren die Funktion "access_control"

Nun widmen wir uns der eigentlichen Hauptfunktion der Klasse.

function access_control( $const ) {
		
		global $Char;
			
			$res = unserialize($Char->rights);
				
			if( !is_array($res) ) {
					
				echo '$res ist kein Array!';
				return;
				
			} else {
					
				if( $res[$const] ) {
						
					return true;
					
				}
				
			}
			
	
	}

Die Variable $const enthält den Namen einer der angegebenen Konstanten (haben wir bereits oben definiert). Da wir die Funktion gleich auch aufrufen möchten und die Werte der einzelnen Daten benötigen, lesen wir die Variable $Char mittels global ein. 

Nun geht es darum, die Daten des Feldes "rights" (ist in der Tabelle gespeichert) auszulesen. Da der Wert von "rights" allerdings ein serialisiertes Array ist, müssen wir dieses erst einmal mittels unserialize() unserialisieren. 

Sollte das Ergebnis davon kein Array sein, wird die Funktion auch hier wieder abgebrochen. Ist $res allerdings ein Array, wird nun geprüft, ob die angegebene Konstante (den Wert dieser Konstante laden wir mit $const) im Array enthalten ist und ob diese den Wert 1 hat. Die Konstante , sofern sie vorhanden ist, wird im Array als "Index" oder auch "Array-Schlüssel" gespeichert.


 

Schritt 9: Wir definieren die Funktion check_admin

Da wir nun die einzelnen Rechte checken können, bräuchten wir eventuell noch eine Funktion, die überprüft, ob der User auch das angegebene Adminlevel oder einen höheren Level hat. Sollte der User einen niedrigeren Level haben, wird ihm der folgende Text (If-Abfrage) oder Link nicht angezeigt.

function check_admin( $level ) {
		
		global $Char;
			
			if( $Char->admin >= $level ) {
				
				return true;
			
			}
	
	}


Schritt 10: Unsere Klasse ist nun fertig!

Nun ist unsere Klasse fertig. Sie sollte in etwa so aussehen:

<?php

/**
 * Eine kleine, simple Access Control Klasse.
**/

class Security {
	
	const ACCESS_USER_EDITOR = 1;
	const ACCESS_USER_BANNED = 2;
	const ACCESS_CHAT_COMMENTS = 3;
	const ACCESS_USER_RENAME = 4;
	
	var $data = array();
	
	public function __construct( $id ) {
		
		if( !empty($id) ) {
			
			$query = mysql_query('SELECT * FROM users WHERE id='.$id);
			
			if( mysql_num_rows($query) == 1 ) {
				
				$this->data = mysql_fetch_assoc($query);
			
			} else {
				
				echo 'Konnte den angegebenen User nicht laden.';
				return;
			
			}
		
		} else {
			
			echo 'Ohne Benutzer-ID kann ich leider nichts aus der Datenbank laden, sorry.';
			return;
		
		}
	
	}
	
	public function &__get( $field ) {
		
		return $this->data[$field];
	
	}
	
	function access_control( $const ) {
		
		global $Char;
			
			$res = unserialize($Char->rights);
				
			if( !is_array($res) ) {
					
				echo '$res ist kein Array!';
				return;
				
			} else {
					
				if( $res[$const] ) {
						
					return true;
					
				}
				
			}
			
	
	}
	
	function check_admin( $level ) {
		
		global $Char;
			
			if( $Char->admin >= $level ) {
				
				return true;
			
			}
	
	}

}
?>

Und nun noch ein kleines Beispiel, wie sie verwendet werden kann:

<?php

mysql_pconnect('localhost','root',''); // Wir erstellen eine MySQL-Verbindung. (XAMPP-Daten.)
mysql_select_db('access_control'); // Wir wählen eine Datenbank aus.

require_once 'access_control.php'; // Ich habe die Klasse in der Datei 'access_control.php' abgespeichert.

$Char = new Security(1); // Wir starten die Klasse und lesen die Daten von User '1' aus.

if($Char->access_control(Security::ACCESS_USER_EDITOR)) { // Die If-Abfrage, ob der User die Rechte besitzt, um einen anderen User zu editieren.
	
	echo 'Der User <b>'.$Char->login.'</b> hat die Berechtigung, andere User zu editieren. Des Weiteren ist <b>'.$Char->login.'</b> ein Admin der Stufe <b>'.$Char->admin.'</b>.';
	// Wir haben noch ein paar Daten des Users abgefragt. Login, Adminstufe. 

} else {
	
	echo 'Der User <b>'.$Char->login.'</b> hat nicht die Berechtigung, einen anderen User zu editieren!';
	// Sollte der User die erforderlichen Rechte nicht besitzen.

}

if( $Char->check_admin(1) ) { // Wir prüfen, ob der User ein Admin mindestens der Stufe 1 ist.

	echo 'Der User '.$Char->login.' ist ein Admin der Stufe 1!'; // Wenn er es ist.
	
} else {
	
	echo 'Der User '.$Char->login.' ist kein ein Admin der Stufe 1!'; // Wenn er es nicht ist.
	
}

?>

Ich hoffe, dass es für alle verständlich war / ist. Ich bin nicht so der beste Erklärer. *lach.
Vielleicht kann es ja jemand gebrauchen..

Liebe Grüße,
der Joel aka Swinq.




Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von I3uLL3t
  • 21.10.2011 - 00:14

thx gut verständlich auch für anfänger wie mich :D

Portrait von AustrianKiller
  • 10.07.2011 - 20:27

so eine Tutorial habe ich schon lange gesucht!
thx

Portrait von wahke
  • 26.12.2010 - 01:03

danke das ist was ich gesucht habe :P

Portrait von Swinq
  • 03.09.2010 - 15:16

Dazu habe ich ein Formular, welches mit diversen Checkboxen gefüllt ist.

Aber ich denke Deine Frage bezieht sich eher auf die spätere Erstellung des Arrays. Dafür benutze ich eine einfache Foreach-Schleife mit einer If-Anweisung.

z.B.

foreach( $_POST as $key => $val ) {

if( $val == true ) {

$arr[$key] = true;

}

}

z.B.

Portrait von dlogic
  • 27.08.2010 - 15:14

Verständlich geschrieben und gut nachvollziehbar... besonders interessant wenn man einem Admin/User Rechte aus einem Pool zuweist ohne dabei die Rechte zuvor in Gruppen kategorisieren zu müssen oder zu können. Meine Frage, wie serialisierts du das Array beim Anlegen/updaten eines Admins und schreibst diese in die DB? Sprich, es gibt mehrere Checkboxen die angeklickt wurden.

Portrait von Swinq
  • 24.08.2010 - 21:30

Nehmen wir nun einfach mal an, wir haben ein Browsergame. In diesem Browsergame gibt es (lass es) 14 Administrative geben. Jeder Admin hat allerdings eine andere Stufe in der Verwaltung des Spiels. Der eine verwaltet zum Beispiel die Rassen, ein anderer wiederum die geschrieben Chatkommentare, usw.! Mit dieser Klasse brauch man nun nicht für jeden Admin eine einzelne Adminstufe anlegen oder ein neues Feld in der Datenbank erstellen welches die Rechte verwaltet. Mit dieser Klasse erstellt man einfach ein einzelnes Feld in der Datenbank und speist dieses mit einem serialisiertem Array was die Rechte des angegebenen Users beinhaltet.

Was so weit allerdings schon erklärt war.. Sorry, bin nicht so der beste Erklärer..

Portrait von BlackBoSs
  • 22.08.2010 - 23:00

für was ist Simple Acces Control gut ? :)

x
×
×