Binäres Rechtesystem

  • Themenstarter Themenstarter Bgag
  • Beginndatum Beginndatum
Wo du Recht hast, hast du Recht. Ich werde es gleich mal ändern.
MfG, Andy

//EDIT: Der Fehler wurde im Quellcode behoben.
 
Zuletzt bearbeitet von einem Moderator:
Hallo!
Ich entschuldige mich für das doppelte Posting, aber es hat sich etwas getan und es sind neue Fragen entstanden. Ich habe nun die Klasse so umgeschrieben, dass es dem Benutzer möglich ist die Rechte für einen Bereich oder die eines Benutzers, optional anhand einer Id oder eines Namens, abzufragen.

Zudem ist es nun möglich einen neuen Benutzer zu erstellen bzw. einen schon bestehenden User zu editieren. Das Problem liegt jetzt auf der einen Seite bei den verschiedenen Queries, bei denen ich nun leider nicht weiß, ob diese so korrekt bzw. optimal sind. Zudem bin ich mir nicht ganz sicher ob bei den Methoden addUser() bzw. editUser() die Verarbeitung der Arrays $fields und $values via implode() korrekt sind. Kann mir da vielleicht jemand helfen?

Außerdem wurde das Problem der doppelten Einträge in einer der beiden Tabellen, über den zusätzlichen Parameter UNSIGNED für das Feld name, behoben. Haltet ihr das für ausreichend oder wäre eine Überprüfung durch eine Abfrage besser?

Leider tritt noch ein Fehler beim Löschen eines "Bereichs" aus der Tabelle permissions auf. Woran kann das liegen. Das betreffende Query sieht für mich vollkommen richtig aus.

Des weiteren würde mich eure Meinung zu der Fehlerbehandlung in dieser Klasse interessieren. Sollen Fehler mit Exceptions behandelt werden oder soll alles über boolesche Werte geregelt werden, sodass der Nutzer der Klasse eigene Fehlermeldungen generieren kann?

Die Klasse ist in ihrer neuen Form angehängt. Testen konnte ich sie leider noch nicht, da mir an meinem momentanen Aufenthaltsort keine Testumgebung zur Verfügung steht. Ich bitte daher um Entschuldigung, falls kleinere Fehler übersehen wurden. Ich würde mich trotzdem sehr über Hilfe oder weitere Anregungen zur Optimierung oder Erweiterung der Klasse freuen.
MfG, Andy
 
Zuletzt bearbeitet von einem Moderator:
Ich frage mich gerade, ob das gesamte System überhaupt sinnvoll beziehungsweise schlüssig ist. Denn einerseits sind damit nur maximal 64 Einträge möglich (BIGINT UNSIGNED ist auf 2?? beschränkt). Andererseits verstehe ich nicht, wieso bei einem neuen Eintrag zwar das nächste Bit verwendet wird, der neue Wert aber einen eigenen Datensatz bekommt.
 
Ich denke 64 interne Bereiche oder Rechte sind für meine Bedürfnisse vollkommen ausreichen. Außerdem kann man da ja auch etwas tricksen. Man könnte zum Beispiel einfach Varchar in der Datenbank benutzen und vor dem Eintragen prüfen ob es sich bei der übergebenen Variable um einen Integer handelt. Nötig sollten solche Schludereien aber meiner Meinung nach garnicht sein.

Zudem würde mich interessieren, welche Alternative du siehst, als jedem neuen Wert einen eigenen Datensatz zu geben. Es geht ja momentan speziell darum es möglichst einfach zu machen die Rechte für Bereiche wie News, Statistiken, generelle Einstellungen, Artikel und was ein CMS noch alles haben kann, zu unterscheiden. Verfeinern kann man das natürlich auch noch.

Mir fällt des weiteren gerade ein, dass es ja reichen würde den Exponenten jedes Bereichs in der Datenbank zu speichern bzw. die Spalte perms in der Tabelle permissions komplett entfallen zu lassen und die Id für einen Bereich als Exponenten zu nutzen. So würde die Tabelle Schlanker, die Klasse vereinfacht und die Anzahl der möglichen Bereiche mehr als verzehnfacht.

Was meinst du? Wäre das eine akzeptable Lösung?
MfG, Andy
 
Ich weiß ja eben nicht, wie du dir das Ganze gedacht hast. Wie sähe beispielsweise eine solche Tabelle samt Beispielwerte aus und welche Bedeutung haben sie?
 
Also es gibt zwei Tabellen. Die Benutzer-Tabelle und die Rechte-Tabelle. Die Benutzer-Tabelle kann unterscheidlich aussehen. Der einfachste Fall wäre aber wohl der folgende.
Code:
id	| name	| pwd	| rights
-------------------------------------------------------------
1	| avedo	| 104bn      | 31 (11111)
2	| peter	| 110dm     | 16 (10000)
3	| klaus	| md640     | 12 (01100)
4	| maic	| 8d9f0       | 11 (01011)
Um die Werte in der letzten Spalte rights verstehen zu können muss man jetzt auf die Tabelle permissions einen kurzen Blick werfen.
Code:
id	| name		| rights
------------------------------------------------------------------
1	| news		| 1 (00001)
2	| articles		| 2 (00010)
3	| database		| 4 (00100)
4	| user		| 8 (01000)
5	| settings		| 16 (10000)
Wie man schnell erkennt stehen in der dritten Spalte der Tabelle nur Zweierpotenzen. In Klammern hinter den Werten in den Spalten rights in beiden Tabellen steht die jeweilige Zahl als Binärwert (wird von rechts gelesen). Beim Vergleich der Werte und der Tabellen im Allgemeinen stellt man einiges fest. Addiert man alle Bereiche erhält man die Rechte von avedo (31). Addiert man allerdings nur die Rechte von news, articles und user, erhält man die Rechte von maic (16). Interessanter wird es nun wenn man anstatt der Dezimalzahlen die Binärwerte.
Code:
  01000 (2^3)
+00010 (2^1)
+10100 (2^4 + 2^2)
-------------
=11110 (2^1 + 2^2 + 2^3 + 2^4)
Man kann also genau feststellen welche Zweierpotenzen hier addiert werden. Geht man also über das binärsystem kann man aus jeder beliebigen Zahl die Zweierpotenzen und somit in unserem Beispiel die Rechte der User für die verschiedenen Bereiche extrahieren. PHP liefert uns für diese Aufgabe, wie schon erwähnt die Bit-Operatoren. In unserem Fall den &-Operator. Den mathematischen Hintergrund dafür bildet der binäre UND-Operator.
Hoffe dass dir das geholfen hat das ganze etwas besser zu verstehen.
MfG, Andy
 
So müsste man aber genausoviele Bits zur verfügung haben wie man Bereiche hat... Ich denke eine Lösung mit User-Gruppen wär sicher einfacher und würde auch gut in das System passen.

Dann könnte man beispielsweise sagen:
Gruppe 1 = News schreiben
Gruppe 2 = Gästebucheinträge löschen, Downloads hinzufügen
Gruppe 3 = Dies und das...

Dann könnte man sich die Userrechte nach dem von Catull ausführlich beschriebenen Rechtesystem zusammenstellen...

Andererseits könnte man auch Userlevel nehmen - also wer Bit 2 Hat hat auch automatisch alle Userlevel darunter. Dafür müsste man aber nicht unbedingt Bitweise nehmen sondern könnte genausogut einfach Integerwerte nehmen... Und das ist hier ja nicht gefragt

Habe den Thread nicht komplett gelesen - hoffe ich wiederhole nicht zuviel ;)

lg
 
Guten Abend!
Ich habe das komplette System nochmals überarbeitet und optimiert. leider funktioniert das gnaze noch nicht wirklich und daher möchte ich euch zunächst das neue System vorstellen und euch dann um Hilfe bitten.

Wie schon zuvor soll es zwei Tabellen, eine für die User-Daten und eine für die Daten der "privaten" Bereiche geben. Die User-Tabelle enthält also im einfachsten Fall id | name | password | permissions. Die Tabelle für die "priavten" oder einfacher gesagt, für die geschützten Bereiche, enthält allerdings nun nur noch den Namen des Bereichs und eine zugehörige ID.

Wie findet man allerdings nun mit dem binären Wert aus der Permissions-Spalte der User Tabelle heraus, ob ein Benutzer zugriff auf einen bestimmten Bereich hat oder nicht? Oder auf welche Bereiche er überhaupt zugriff hat? Die Lösung ist eigentlich einfach. Nimmt man die ID für einen bestimmten bereich in zum Beispiel einem CM-System und nutzt diesen als Exponent zur Basis zwei, so erhält man den binären Wert, den der User als Teil seines binären Wertes besitzen muss.

Möchte man nun also alle IDs der Bereiche herausfinden, zu denen ein User Zugriff besitz, kann man dies relativ einfach auszählen. Ein Beispiel:

Es gibt die Bereiche bla(ID 1), lol(ID 2), omg(ID 3) und nop(ID 4).
Möchte nun jemand zum Beispiel den benötigten Binärwert zu bla wissen, muss er nur 2^ID(lol) = 2^2 = 4 rechnen.
Möchte man also alle Bereiche wissen, zu denen ein Benutzer Zugriff besitzt, muss man einfach nur nach dem größten möglichen Exponenten zur Basis zwei suchen, bei dessen Subtraktion vom binären Permissions-Wert des Users nicht null herauskommt. Man durchläuft also eine Schleife solange, bis kein Restwert der Permissions mehr da ist. Gibt es also einen Nutzer Klaus mit dem binären Permissions-Wert 20 in meinem oben begonnenen pseudo CM-System, so setzen sich seine Werte wie folgt zusammen.
P(Klaus) = 2^ID(nop) + 2^ID(lol)
Der Benutzer Klaus hat also Zugriff auf die Bereiche nop und lol.

In PHP kann man dies, wie schon gesagt mit einer Schleife leicht errechnen.
PHP:
// permissions of Klaus
$perms = 20;

//start counter
$i = 0;

// initiate array of ids
$mods = array();

// extrahate specific permissions
do
{
    if( (($p-pow(2,$i)) < 0) )
    {
        $e = $i-1;
        $p = $p-pow(2,$e);
        $mods[] = $e;
        $i = 0;
    }

    else
    {
        $i++;
    }
}
while( (($p-pow(2,$i)) < 0)  && ($p > 0) )
Nach Durchlaufen der Schleife enthält das Array $mods alle IDs zu den geschützten bereichen zu denen Klaus Zutritt besitzt, also 2 und 4.

Ich hoffe, dass das neue System klar geworden ist. Bei Fragen stehe ich natürlich gerne zur Verfügung und für Anregungen bin ich auch immer offen.

Doch, wie schon gesagt, funktioniert die umgeschriebene Klasse noch nicht ganz. Es tritt folgender Fehler auf und ich finde ihn einfach nicht, wodurch ich die Klasse auch noch nicht testen konnte.

Code:
Parse error: syntax error, unexpected T_RETURN, expecting ';' in /home/www/web193/html/permissions.php on line 180

Ich hoffe mir kann jemand helfen. Ich wäre sehr dankbar. Die betreffende Zeile ist übrigens die mit der while()-Schleife in der getPerms()-Methode.
MfG, Andy

Übersicht über die Methoden
__construct() - Setzt die wichtigen Variablen
addMod() - Fügt einen geschützten Bereich hinzu
delMod() - Entfernt einen geschützten Bereich
getMods() - Gibt die IDs aller geschützter bereiche zurück
getPerms() - Gibt die IDs zu den Bereichen zu denen ein Benutzer Zutritt besitzt zurück
addUser() - Fügt einen Benutzer hinzu
check() - Überprüft die Zutritts-Berechtigung eines Nutzers
getId() - Gibt die ID zu einem Bereich oder einem Nutzer anhand der ID oder des Namens zurück
 
Zuletzt bearbeitet von einem Moderator:
Hi,

schön das du hier weiter machst.
Um den Fehler zu beheben einfach ein Semikolon nach der while() Schleife setzen.
PHP:
while( (($p-pow(2,$i)) < 0)  && ($p > 0) );
Grüsse
 
Danke für den Tipp. Den Fehler hätte ich in den nächsten Stunden wohl nicht gefunden. So konnte ich nun wenigstens das Script testen, auch wenn es noch nicht wirklich funktioniert. Und zwar Funktioniert das Löschen eines Bereichs via delMod() noch nicht und die IDs aller Bereiche können auch noch nicht via getMods() zurückgegeben werden. Die Methode gibt zwar die erste ID korrekt zurück, aber nur die erste, obwohl sie, wie im Testaufruf am Ende des Scripts zu sehen ist, später noch weitere IDs von neuen Bereichen ausgeben soll. Ich vermute mal stark, dass mein Problem bei den Queries liegt, kann dies aber nicht mit Sicherheit sagen. Kann mir da noch jemand weiterhelfen?
MfG, Andy
 
Zurück