# Berechtigungskonzept - Bitte um Feedback



## beta20 (5. Jan 2016)

Hallo,

ich habe folgenden String:
<!SPECIFIC_U?id=1;id=3%!><!SPECIFIC_V?id=1;id=3%!>

Was ich nun benötige ist:

Hallo,

ich möchte gerne ein komplexeres Berechtigungssystem in meiner WebApp einbauen.
Folgendes Konzept habe ich:

a) Es gibt verschiedene Entities, die eine Berechtigung haben:
- Customer
- Visitor
- User
- Job

All diese benutzen die Klasse "Permission".
Jetzt meine Frage, ob das technisch ok ist oder ob es Probleme mit damit geben kann:
Ich lege einen Job an. Ein Job hat genaue eine Permission, in der gespeichert wird welche Berechtiungsstufe wer darf.
In der Webapplikation gebe ich dann in einer MultiCheckBox an:

Als Beispiel die Berechtigung "userAnlegen" im Job:
o Customer
o Visitor
o User
o Bestimmter User

=> Hier wird dann abgehakt wer was darf.

Nun speichere ich das in einem String ab - z.B. Customer und Visitor haben die Berechtigung:
String s = "<Customer><Visitor>"

In einer Abfrage, ob das Objekt nun die Berechtigung hat oder nicht, wird so abgefragt:
if(s.contains("<Customer>")
  // Ja, hat Berechtigungen....

Als weitere Stufe sollen nur bestimmte User die Berechtigung haben:
Das stelle ich mir so vor:
"<SPECIFIC_U?id=1;id=3%>"

Ich speichere mir hier die ID des Users:
Die ID´s schneide ich dann aus dem String heraus und prüfe dann wieder in einer anderen Methode ab, ob das eingeloggte Objekt (Visitor, User etc.) die ID hat oder nicht.

Ist das Konzept ok oder kann man das total in die Tonne kloppen?
Danke für jede Hilfe


----------



## kneitzel (5. Jan 2016)

Also ich verstehe hier im Augenblick nicht genau Dein Vorhaben. Was ich verstanden habe ist, dass Du gerne ein Berechtigungskonzept in Deine Lösung einbauen möchtest.
Generell mag da vieles gehen aber ich möchte einfach einmal ein paar Gedanken, die mir so in den Sinn gekommen sind, weiter geben:
- Ich würde auf jeden Fall sicher stellen, dass der Code in sauberen Klassen extrahiert ist. Dadurch kannst Du die Implementation später anpassen.
- Die Idee, einen Substring in einem String zu suchen hat zwei Probleme.
  a) Wenn Du mehr Rollen hast, dann ist dies einfach langsam. Für kleine Tests evtl. ok aber wirklich nutzbar: nö-
  b) Sicherheitsbedenken: Wenn ich Rollen selbst anlegen könnte, dann könnte ich evtl. die Zeichen < > verwenden und schon kann es evtl. zu Fehlern kommen bei der Auswertung, weil <Customer> nicht mehr eindeutig ist. 
- Diese Anforderung ist doch nichts neues. Da gibt es also massiv Lösungen. Ich würde Dir raten, die vorhandenen Lösungen anzusehen.

Generell gibt es da zwei Gesichtspunkte: Einmal die eigentliche Anmeldung. Ein Anwender muss sich anmelden. Da gibt es viele verschiedene Möglichkeiten für. Und dann die Autorisierung. Ein angemeldeter Benutzer hat bestimmte Rechte.

Hier gefällt mir ein Modell ganz gut:
- Die Applikation definiert nur Aktionen und prüft dann genau diese ab. Es gibt also eine Liste von Operationen die alle eine Nummer haben. Operationen können dann alles sein. Seite x anzeigen, User ändern, User löschen, ...
- Es gibt ein File/Datenbank/was auch immer das beim Start oder bei Bedarf gelesen wird. Dieses enthält dann zum einen eine Definition von Rollen. Ein Admin darf diese Operationen, ein User jene und ein gast nur ein paar wenige. Und zum anderen ggf. weitere notwendige Informationen wie z.B. eine Gruppenzugehörigkeit oder eine Zuweisung von Usern. Dies separiert dann die Entwicklung von der Rechtezuordnung. Ich als Entwickler interessiere mich nicht dafür, was für Rollen ein Nutzer später evtl. haben will. Ich muss nur klar ermitteln können, ob ein User etwas darf oder nicht. Das aber nur als eine Idee, wie es aussehen könnte.

Bezüglich der Datenhaltung: Hast Du Dich schon einmal mit den Datentypen in Java vertraut gemacht? Ehe ich irgend eine Lösung angehe, sollte ich diese Grundlagen halbwegs kennen. Du baust da ja einen String auf, der ja eigentlich mehrere Strings ist. Also wäre dein "String s" doch eigentlich ein Array von Strings. Und dann willst Du darin suchen und es soll ggf. dynamisch sein: Schon landet man dann bei anderen Lösungen, die die Java Library bietet, die dann alles auch deutlich performanter macht. Bei dem Vergleich von Strings könnte man, so dies oft gemacht wird, einmal die Hashcodes ermitteln und dann diese zuerst checken was deutlich schneller ist. Oder ich kann Daten, bei denen die Reihenfolge egal ist, sortiert aufbewahren. Dann hat man Suchbäume und so. Aber das muss man nicht im Detail alles kennen: es reicht, sich mit den Datentypen vertraut zu machen und diese dann einfach zu nutzen.

(Wobei es auch durchaus interessant sein sein, einen BalancedBinaryTree zu schreiben. Auch wenn es für den eigentlichen Applikationsentwickler nicht wirklich benötigt wird.)

Konrad


----------



## beta20 (5. Jan 2016)

Was mir Probleme bereitet ist:

a) Ein Job hat genau eine Entity "Permission"
  Dort wird definiert welche Berechtigungsobjekte (Visitor, User etc.) was machen darf.
  Beispiel: Wer darf kommentieren?
  Nun habe ich in der Web Oberfläche eine Liste der Berechtigungsobjekte (also wieder Visitor, User etc.)
  Hake ich dann Visitor an, dürfen ALLE Visitor das.
  Hake ich zusätzlich User an, dürfen alle User das

Die Permission, die am Job hängt, ist eigentlich mehr ein Template der Berechtigungen.
Im Moment weiß ich nicht, wie ich das anderst als in einem String machen kann, dass ich direkt mehrere Objekte einer Berechtigung zuweisen kann.
Außer ich mache dann natürlich boolean für jede Ausprägung:
- createCommentVisitor
- createCommentUser
- ....
=> Dann brauche ich aber Zig Attribute

Als Template meine ich:
- Ein Visitor gehört immer zu einem Job.
=> Wird nun ein Visitor angelegt, dann wird für diesen Visitor ebenfalls ein Objekt das "Permission" Entity angelegt.
  Also Visitor 1...1 Permission
  Die Permission werden nun durch das Template des Jobs automatisch gesetzt.
  Demnach wird beim Erstellen des Visitor eine Methode aufgerufen, die dann prüft was ein Visitor darf:
  Wurde also im Job definiert, dass ein Besucher kommentieren darf, dann wird beim Attribut "createComment" auf "true" gesetzt.
  Etwa so:

```
if(job.getPermission().getCreateComment().equals("Visitor"))
      Permission p.setCreateComment("true");
```

Wäre das ein Ansatz?


----------



## kneitzel (5. Jan 2016)

Also zum einen fällt mir auf, dass Du scheinbar sehr an Strings hängst. Klammer Dich nicht an Strings. Das ist ein absoluter Fehler und führt mit der Zeit nur zu Problemen.

Und ich verstehe Dein Konstrukt noch noch nicht wirklich. Ich habe Probleme, zu verstehen, was ein Job oder so ist.

Ich erläutere Dir einfach einmal ein kleines Schema, das Du aufbauen könntest.

Zum einen hättest Du Aktivitäten. Für alles, was gemacht werden kann, gibt es eine Aktivität. Also z.B. Seite1anzeigen, User anlegen, User editieren, User Löschen, ... Dies kann eine einfache Enumeration sein.

Dann hast Du Rollen. Rollen haben:
- einen Namen (String z.B.  "Administrator", "User", "Moderator", "Gast")
- eine Menge an Aktivitäten, die ausgeführt werden können.

Dann hast Du User:
- Diese haben eine Namen
- eine Möglichkeit sich zu autorisieren (z.B. Login/Password oder per OpenID, Facebook, ...)
- Rollen

Wenn Du nun prüfen musst, ob der User das Recht hat, eine Aktivität durchzuführen, dann ist wichtig, dass Du den User an der Stelle zur Verfügung hast. Also hat das User-Objekt eine Funktion darf.
Alles was Du dann aufrufen musst ist ein user.darf(Aktivitäten.EineDerAktivitäten) und du bekommst zurück, ob der User die Aktivität ausführen darf oder nicht. Ist auch relativ einfach zu implementieren.
User hat ja eine Menge an Rollen und für jede Rolle muss nur geprüft werden, ob die Aktivität enthalten ist. Sobald dies der Fall ist, wir true zurück gegeben. Sind alle Rollen geprüft und es wurde nicht gefunden, dann wird false zurück gegeben.
Die Klasse Rolle hat eine Menge an Aktivitäten. Und hier kann dann bei der Prüfung auf eine Aktivität auch einfach das contains geprüft werden.

Jetzt müssen wir nur überlegen, was denn diese "Menge an" sein kann. Dazu hat Java eine ganze Menge an sogenannten Collections, die man da verwenden kann. Die solltest Du Dir einfach einmal ansehen und Du wirst bestimmt fündig. Wenn Du Probleme hast, was passendes zu finden, dann helfen wir dir auch gerne weiter.

Was dann natürlich noch fehlt ist das Speichern der Daten. Das kannst Du über Datenbanken machen oder einfach über eine Serialisierung der Daten. Müsstet Du auch einmal nachlesen.

Konrad


----------



## beta20 (5. Jan 2016)

Wie soll das dann deiner Meinung datenbanktechnisch implementiert werden?

Wenn ich das so richtig verstehe, dann:

Wenn ich User A habe, der z.B. "Seite1anzeigen", "Kommentar schreiben" darf.
Dann habe ich in der Tabelle "Aktivität"

User:
ID = 2

ID  Aktivität User_FK
1   SeitenAnzeigen  2
2   Kommentar schreiben 2

Das heißt am Ende des Tages habe ich 500 User.
Im Durchschnitt hat jeder User 10 Berechtigungen
=> Heißt ich habe insgesamt mind. 5000 DB - Einträge


----------



## kneitzel (5. Jan 2016)

Relationen in Datenbanken sind doch trivial abzudecken:

1:n Beziehungen sind über ein Feld abzudecken.
n:m Beziehungen sind über eine weitere Tabelle abdeckbar.

Und eine Tabelle mit 5000 Einträgen ist doch absolut kein Thema.

Und ich würde Rollen zwischenschalten. Denn die Aktivitäten sollten relativ fein sein und Du willst doch bei einem User nicht später 100 einzelne Berechtigungen setzen. Das reduziert dann auch etwas die Anzahl der Einträge, aber das ist absolut nicht der Grund für die Rollen. Da geht es nur um eine Vereinfachung bei der Zuweisung.

Konrad


----------

