Ergebnis 1 bis 10 von 10

Thema: Benutzerrechte bei Webseiten

  1. #1

    Benutzerrechte bei Webseiten

    Moin.

    Ich plane grad, ein einges CMS zu schreiben. In diesem sollen auch bestimmte Benutzer nur bestimmte Rechte haben. Also dass z.B. Benutzergruppe A nur Artikel verfassen dürfen, während Benutzergruppe B Adminrechte haben und alles dürfen.
    Nun stellt sich mir die Frage, wie wird sowas realisiert? Ist das nur ein Datenbankeintrag, wie z.B. Adminrechte = 1, um Adminrechte zu erhalten oder wird da noch mehr abgefragt, um es sicher zu gestallten?

  2. #2
    Es kommt darauf an was du möchtest. Ich persönlich finde es teils eher doof das eben nur ein "Harken" gesetzt sein muss und der User hat alle rechte, klar es sollte so etwas wie Superuser geben.
    Aber häufig will man ja nicht unbedingt jedem Benutzer alle Rechte gewähren.

    Ich habe es bei meinem CMS an dem ich schon seid längerem sitze, so gelöst das ich einmal den Benutzertyp "Founder" habe. Ob ein Benutzer nun ein Gründer ist ergibt sich aus mehreren Komponenten, aus dem Grund das Gründer eben echt alle Rechte haben.
    Parallel dazu habe ich aber eben die Möglichkeit implementiert eben für bestimmte Dinge Berechtigungen zu vergeben; So dass man z.B. auch Redakteure erstellen kann, die z.B. nur News erstellen dürfen.
    (Gerade das mit den Redakteuren ist z.B. der Grund wieso Typo3 so beliebt ist ...)

    Den Aufbau der Berechtigungen habe ich an Windows angelehnt.
    Mag vielleicht nicht jedem bekannt sein, da man in den Home-Editions keine Berechtigungen setzen kann ...

    Eine Berechtigung kann folgende Zustände annehmen:
    Nicht gesetzt (nein), Ja, Verbieten

    Nehmen wir ein einfaches Beispiel, der Benutzer John-Doe ist in den Gruppen: Buchhaltung, Auszubildende und in der System-Gruppe "Registrierte Benutzer"

    Registrierte Benutzer:
    Nachrichten schreiben: ja
    Nachrichten löschen: nicht gesetzt
    Kommentare schreiben: ja
    Anhänge hochladen: nicht gesetzt

    Buchhaltung:
    Nachrichten schreiben: ja
    Nachrichten löschen: ja
    Kommentare schreiben: nicht gesetzt
    Anhänge hochladen: nicht gesetzt

    Auszubildende:
    Nachrichten schreiben: nicht gesetzt
    Nachrichten löschen: verbieten
    Kommentare schreiben: nicht gesetzt
    Anhänge hochladen: nicht gesetzt

    John-Doe hat dann später folgende Rechte:
    Nachrichten schreiben: ja
    Nachrichten löschen: nein
    Kommentare schreiben: ja
    Anhänge hochladen: nein

    (Rechte mit dem Wert "Nicht gesetzt" können, müssen aber nicht in der Datenbank stehen; jede Berechtigung ist ein Datensatz!)

    Geändert von Xardas der Dunkle (19.08.2009 um 20:54 Uhr)

  3. #3
    Dass mit Gruppe A und B war von mir auch nur ein Beispiel.
    Ich wollte es auch noch ein bisschen mehr aufteilen.

    Mich interessierts, wie man es programmtechnisch löst.
    Ob ich jetzt z.B. in einer MySQL Tabelle eine Spalte mit Rechten einbaue, die dann z.B. eine Reihe von Einsen und Nullen besteht und jede Ziffer steht Ja/Nein oder ob es dort andere Methoden gibt, die es evtl. sicherer machen.

    Also wie z.B. bei deinem Beispiel

    Code:
    ID   Name                    Rechte
    1    Registrierte Benutzer   1010
    2    Buchhaltung             1100
    3    Auszubildende           0000
    ID = Kennziffer der Benutzergruppe
    Name = Name der Benutzergruppe
    Rechte = Rechtevergabe (1= Ja | 0 = Nein), wobei:
    • 1. Ziffer = Nachrichten schreiben
    • 2. Ziffer = Nachrichten löschen
    • 3. Ziffer = Kommentare schreiben
    • 4. Ziffer = Anhänge hochladen


    Oder gibt es da noch eine bessere Methode?

  4. #4
    Es kommt drauf an wie viele Berechtigungen du haben willst, bzw. ob z.B. durch Module weitere Berechtigungen dazu kommen können!

    Ich habe extra folgende Struktur gewählt: 2 MySQL Tabellen.
    In Tabelle 1 Stehen die Namen der existierenden Berechtigungen.
    In Tabelle 2 Steht der Wert zugeordnet zum Namen und zu einer Gruppe oder einem Benutzer.

    Der Wert kann entweder 0, 1 oder 2 sein. Dabei steht:
    0 für "nicht gesetzt" / "nein"
    1 für "ja"
    2 für "verbieten"


    Geändert von Xardas der Dunkle (19.08.2009 um 22:38 Uhr)

  5. #5
    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Code:
    ID   Name                    Rechte
    1    Registrierte Benutzer   1010
    2    Buchhaltung             1100
    3    Auszubildende           0000
    Wenn du in Reichweite sitzen wuerdest, wuerde ich dich fuer dieses Layout erschlagen. Genau so, wie jeder andere Informatiker.

    Wenn du ein CMS baust, dann solltest du natuerlich auch auf die Wiederverwendbarkeit achten. Wenn du deine Rechte-Spalte so anlegst, hast du nur Nachteile. Bereits einfache Abfragen werden zu einem unnoetigen Bit-schieben verurteilt.

    Die etwas bessere, aber immer noch schlechte Loesung waere es, wenn du de einzelnen Flags in jeweils eine Spalte schieben wuerdest. Damit machst du dir aber auch nicht gerade einen Gefallen.

    Etwas schoener waere es, wenn du das Ganze in mehrere Tabellen aufteilst:

    - Usergruppen (id, name)
    - CmsSeiten (id, kennung)
    - Gruppenrechte (Gruppe, Seite)

    In "Gruppenrechte" hast du immer ein 2-Tupel, fuer jede Berechtigung stehen. Wenn du beispielsweise die Seite {1, Statistik} in den Seiten hast, und {2, User}, und du moechtest der Gruppe User den Zugriff auf diese Seite gestatten, dann hast du das 2-Tupel {1, 2} in Gruppenrechte.

    Auf diese Art und Weise kannst du dein CMS eleganter erweitern. Ich wuerde wahrscheinlich noch erlauben, einzelne Seiten zu gruppieren, damit ich eine schoenere Auswahl bei den Gruppeneinstellungen genereiren koennte. Das verlaueft dann wieder nach em selben Prinzip, nur das ich eben die Seiten hinter weiteren Tabellen vor der Rechte-Tabelle verstecke:

    Rechten {id, name}
    SeitenRechte {rechte, seite}

    Um Seiten zu gruppieren, erstellt man wieder einen Gruppeneintrag, und verbindet sie ueber die SeitenRechte seriell mit den Seiten.

    /Xardas
    Was du machst ist zwar schon wesentlich besser, als das was Whiz vorgeschlagen hat, aber auch nicht wirklich sauber. Wenn du dich noch nicht wirklich mit der Idee hinter Db-Design beschaeftigt hast, denkst du ansatzmaessig aber schon in die richtige Richtung. Diese Idee musst du nur noch weiter ziehen.

    EDIT: s/2-Tupel/1-Tupel

  6. #6
    Zitat Zitat
    /Xardas
    Was du machst ist zwar schon wesentlich besser, als das was Whiz vorgeschlagen hat, aber auch nicht wirklich sauber. Wenn du dich noch nicht wirklich mit der Idee hinter Db-Design beschaeftigt hast, denkst du ansatzmaessig aber schon in die richtige Richtung. Diese Idee musst du nur noch weiter ziehen.
    Tut mir Leid aber ich kann dir nicht ganz folgen was du mir damit sagen möchtest.


    Geändert von Xardas der Dunkle (20.08.2009 um 19:10 Uhr)

  7. #7
    Zitat Zitat von Xardas der Dunkle Beitrag anzeigen
    Tut mir Leid aber ich kann dir nicht ganz folgen was du mir damit sagen möchtest.

    Kurzum: Du speicherst laut deiner Beschreibung unnoetige Informationen. Du hast eine Menge von Gruppen. Entweder sie haben eine Berechtigung, oder eben nicht. Im Normalfall haben sie eine Berechtigung einfach nicht.

    Warum speicherst du die ganze Menge, ohwohl eine Untermenge ausreicht? Warum hast du zwei Flags fuer ein und den selben Status?

    Entweder eine Gruppe hat die Rechte, oder eben nicht. Du brauchst nur die Untermenge mit der Berechtigung speichern. Alles Andere ist ueberfluessig und macht die Datenbank nur statischer.

    Sonst machen wir um den Dreh das Selbe, nur das ich es einmal ueber gesperrte Seiten demonstriert habe, und einmal ueber Seitengruppen.

    Wenn man eingermassen fit mit SQL ist, hat man bei meiner Loesung sicher eher angenehmere Abfragen, wenn man minimalistisch vor geht.

  8. #8
    Ich gebe dem vorgeschlagenen Verfahren mal seinen Namen: Access Control Lists (ACLs). ACLs finden sich in allen ernstzunehmenden Betriebssystemen und sind gar nicht mal so schwer.

    Mog hat das ganz gut beschrieben; ich füge dem noch mal als Gedankenexperiment hinzu, daß man ein System aufbauen könnte, in dem alles und jeder eine ACL haben kann.
    Dazu wird so ziemlich alles, was es im System gibt (User, Usergruppen, Blogeinträge, sogar ACLs) in einer zentralen Objekttabelle verzeichnet (hauptsächlich, damit alle Objekte eine ID im selbenden fortlaufenden Nummernbereich haben). Die ACLs weisen dann einfach beliebigen Objekten auf beliebigen anderen Objekten Rechte zu.

    Ach ja; die Objekte sollten hierarchisch organisiert sein, damit Rechtevererbung möglich ist. So kann man Standardregeln festlegen, indem man einfach die ACLs das Wurzelelement referenzieren läßt.

    Die zentrale tabelle folgt in Pseudocode. "#" bezeichnet Kommentare.
    Man verzeihe mir, daß ich vermutlich die Indizes falsch gesetzt habe und Fremdschlüssel gar nicht verwende; Datenbanken habe ich nie formell gelernt, weil der Kurs zeitlich blöde aufwändig ist.

    Zuerst mal hat man eine Tabelle, die die ACL-Einträge beinhaltet:
    Code:
    TABLE ACLEntries
      int        acl_id        # ID der ACL
      int        object_id     # ID des Objekts, auf das zugegriffen werden soll
      int        subject_id    # ID des Objekts, für das die Berechtigung gilt
      varchar    action        # Aktion, die erlaubt/verboten wird
      tinyint(1) isProhibition # Ist der Eintrag ein Verbot?
      INDEX acl_id
    
      # Man hätte für action auch eine ID nehmen können; dann würden alle möglichen
      # Aktionen in einer weiteren tabelle stehen und könnten auch ACLs haben.
    Der Eintrag 300, 10, 35, read, 0 würde also bedeuten, daß die ACL mit der Objektnummer 300 dem Objekt 35 erlaubt, auf Objekt 10 die Aktion read durchzuführen.

    Wenn man den Rest des Systems um diese Tabelle herum konstruiert, ist man bezüglich der Rechtevergabe nur durch das beschränkt, was man in das User Interface einbaut. Man kann theoretisch einzelnen Usern Rechte in Bezug auf einzelne Posts geben und nehmen und niederen Administratoren verbieten, an bestimmten Einstellungen herumzufummeln. Man könnte sogar bestimmten Teilen der Website den Zugriff auf bestimmte andere Teile untersagen.

    Allerdings hat mein System einige Nachteile:
    - Es ist nicht so extrem übersichtlich. Da alle Objekte in der selben Tabelle erfaßt sind muß man irgendwoanders die ganzen Metadaten oranisieren. Außerdem kann man nicht mehr anhand des id-Feldes erkennen, der wievielte Post ein Post nun ist, etc.
    - Es ist auch nicht so extrem performant. Die Objekttabelle wird sehr schnell anwachsen, da jeder Scheiß da eingetragen wird.
    - Außerdem muß die Seite haufenweise Datenbankanfragen stellen, um in Erfahrung zu bringen, was ein Objekt nun darf und was nicht. Vielleicht könnte man da mit stored procedures was reißen, aber so oder so bleibt einiger Overhead.
    - Nicht zu vergessen, daß man die ganzen Abfragen auch alle coden muß.

    Ist eben nur ein kleines Gedankenexperiment, um zu sehen, wie man ACLs auf die Spitze treiben kann.

  9. #9
    Zitat Zitat
    Warum speicherst du die ganze Menge, ohwohl eine Untermenge ausreicht? Warum hast du zwei Flags fuer ein und den selben Status?
    Habe ich nicht. Das Flag verbieten hat eine höhrere Priorität als das Flag "Nein".
    Wenn in einer Gruppe gesagt wird du darfst das in einer anderen du darfst es nicht darfst du es trotzdem.
    Wird es hingegen verboten darfst du es wirklich nicht.

    Ich habe es ja am Beispiel des Azubis versucht zu verdeutlichen. Ein Azubi in der Probezeit soll z.B. nicht direkt die Möglichkeit haben Artikel auf der Seite zu veröffentlichen, er darf aber neue Artikel anlegen und vieles mehr.
    Würde ich sagen es gibt nur Ja und Nein müsste ich 2 Gruppen alle Berechtigungen zuweisen.
    Bei meinem Vorgehen benötige ich zwar auch zwei Gruppen, nur brauche ich der Gruppe "Probezeit" nur eine Berechtigung zuweisen und zwar: "Veröffentlichen verbieten".



    Diese Tabelle hat jetzt zwar echt etwas overhead nämlich das Feld record_class dieser ergibt sich aber durch das zugrunde liegende ORM und wird eig. erst wichtig wenn ich die Klasse Permission noch einmal ableiten würde.

    Code:
    --
    -- Tabellenstruktur für Tabelle `xcms_permission_value`
    --
    
    CREATE TABLE IF NOT EXISTS `xcms_permission_value` (
      `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
      `record_class` enum('Permission') COLLATE utf8_bin DEFAULT 'Permission',
      `name_id` int(12) unsigned DEFAULT NULL,
      `user_id` int(12) unsigned DEFAULT NULL,
      `group_id` int(12) unsigned DEFAULT NULL,
      `object_class` varchar(255) COLLATE utf8_bin DEFAULT NULL,
      `object_id` int(12) unsigned DEFAULT NULL,
      `value` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=21 ;
    
    --
    -- Daten für Tabelle `xcms_permission_value`
    --
    
    INSERT INTO `xcms_permission_value` (`id`, `record_class`, `name_id`, `user_id`, `group_id`, `object_class`, `object_id`, `value`) VALUES
    (1, 'Permission', 1, NULL, 1, 'Sitetree', 2, 1),
    (2, 'Permission', 1, NULL, 2, 'Sitetree', 2, 1),
    (3, 'Permission', 1, NULL, 3, 'Sitetree', 2, 1),
    (4, 'Permission', 1, NULL, 4, 'Sitetree', 2, 1),
    (5, 'Permission', 1, NULL, 1, 'Sitetree', 4, 1),
    (6, 'Permission', 1, NULL, 2, 'Sitetree', 4, 1),
    (7, 'Permission', 1, NULL, 3, 'Sitetree', 4, 1),
    (8, 'Permission', 1, NULL, 4, 'Sitetree', 4, 1),
    (9, 'Permission', 1, NULL, 1, 'Sitetree', 5, 1),
    (10, 'Permission', 1, NULL, 2, 'Sitetree', 5, 1),
    (11, 'Permission', 1, NULL, 3, 'Sitetree', 5, 1),
    (12, 'Permission', 1, NULL, 4, 'Sitetree', 5, 1),
    (13, 'Permission', 1, NULL, 1, 'Sitetree', 6, 1),
    (14, 'Permission', 1, NULL, 2, 'Sitetree', 6, 1),
    (15, 'Permission', 1, NULL, 3, 'Sitetree', 6, 1),
    (16, 'Permission', 1, NULL, 4, 'Sitetree', 6, 1),
    (17, 'Permission', 1, NULL, 1, 'Sitetree', 7, 1),
    (18, 'Permission', 1, NULL, 2, 'Sitetree', 7, 1),
    (19, 'Permission', 1, NULL, 3, 'Sitetree', 7, 1),
    (20, 'Permission', 1, NULL, 4, 'Sitetree', 7, 1);

  10. #10
    Zitat Zitat von Xardas der Dunkle Beitrag anzeigen
    Habe ich nicht. Das Flag verbieten hat eine höhrere Priorität als das Flag "Nein".
    Wenn in einer Gruppe gesagt wird du darfst das in einer anderen du darfst es nicht darfst du es trotzdem.
    Wird es hingegen verboten darfst du es wirklich nicht.
    Mit anderen Worten: "Nein" bedeutet "hat keine Erlaubnis". "Verboten" bedeutet "darf nicht, auch wenn er eine Erlaubnis hat". Das macht Sinn, weil ACLs in der Regel hierarchisch arbeiten, ein Objekt also die ACLs seiner Elternobjekte erbt. Ich kann also für das Elternobjekt eine Erlaubnis haben und für das Kindobjekt nicht – damit würde ich im Kindobjekt trotzdem Zugriff kriegen, sofern es nicht verboten wird.

    Dabei "überstimmen" normalerweise Kinder- die Elternobjekte. Nehmen wir folgendes Szenario:
    Code:
    Foo (Zugriff erlaubt)
     +- Quux (kein ACL-Eintrag)
     +- Bar (Zugriff verboten)
         +- Baz (Zugriff erlaubt)
         +- Blubb (kein ACL-Eintrag)
    Dann sehen meine Rechte so aus:
    - Foo: Ich kann zugreifen.
    - Quux: Ich kann zugreifen.
    - Bar: Ich kann nicht zugreifen.
    - Baz: Ich kann (theoretisch) zugreifen. Ich kann zwar nicht über Bar hinnavigieren, Direktzugriff könnte aber gehen.
    - Blubb: Ich kann nicht zugreifen.

    Falls man auf Objekte nur zugreifen kann, wenn man auch an die Elternobjekte kommt, so reicht ein Verbot irgendwo in der Kette der Eltern, damit ich keinen Zugriff mehr habe.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •