AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Windows-Berechtigungen (Benutzer/Gruppen) im eigenen Programm verwenden

Windows-Berechtigungen (Benutzer/Gruppen) im eigenen Programm verwenden

Ein Tutorial von berens · begonnen am 17. Aug 2015
Antwort Antwort
berens
Registriert seit: 3. Sep 2004
Vorwort
Hallo zusammen. Dieses Tutorial entsteht notgedrungen aus der Situation, dass es für Delphi ohne tiefgehende API Kenntnisse schwer möglich ist, einen Einstieg in die Rechteverwaltung zu finden. Mit meinen gesammelten Erfahrungen beim Einstieg in die Thematik möchte ich nun anderen Leuten die Tür zu dieser Thematik öffnen. Da ich selbst mich selbst weder mit den notwendigen APIs, noch tiefgehend mit der (hier gleich vorgestellten) JwSCL auskenne, mögen mir die Profis bitte alle sachlichen und inhaltlichen Fehler verzeihen, und diese zur Korrektur bekannt geben.

Die API zur Rechteverwaltung ist sicherlich im MSDN, und die JwSCL unter dem u.g. Link einwandfrei dokumentiert, aber wenn einem die Zusammenhänge fehlen... Leider sind die Beispiele der JwSCL nicht wirklich kommentiert, so dass schon der pure Zweck der ausführbaren Demos mir ein Rätsel bleibt, alle weil diese auch teilweise direkt nach dem Klick eines Buttons Exceptions werfen, statt aussagekräftig etwas zu demonstrieren :/

Da ich nun also weder die Thematik, noch die Werkzeuge vollständig beherrsche, ist dies ein eher "pragmatisches" Tutorial, wie man ganz bestimmte Sachen machen kann. Technische Details bleiben hier manchmal vielleicht unerwähnt, einige Sachen machen die Profis bestimmt anders oder sogar "richtig", aber bevor Ihr -wie ich- gar keinen Einstieg zu den Themen hinbekommt, hier erstmal zum Anschauen wie man die grundlegendsten Sachen macht.

Disclaimer
Keine Garantie auf Korrektheit oder Vollständigkeit. "Sicherheit" in Software ist ein wichtiges Thema, mit dem nicht leichtfertig umgegangen werden sollte, speziell wenn sensible Daten gefährdet sind. Die JwSCL sind meines Erachtens gute "Header", aber auch könn(t)en Fehler vorhanden sein. Dieses Tutorial kann keinen 100% Schutz Eurer Software, der Kundendaten etc. garantieren!

Sinn und Zweck
Gerade in großen Firmen soll nicht "Jeder"-"Alles" dürfen. Man kennt das von den Dateiberechtigungen der Festplatte oder der Datei- und Druckerfreigabe. Man kann bestimmten Benutzern oder Gruppen erlauben etwas zu tun, und bestimmten Benutzern oder Gruppen explizit verweigern etwas zu tun. Hier im Forum findet man viele Tipps, wie man Dateiberechtigungen ändern kann, aber nicht, wie man in seinem eigenen Programm nur bestimmten Benutzern etwas erlaubt oder verbietet. Diese Lücke soll das Tutorial schließen, und befasst sich ausschließlich hiermit.


Einstieg und Begriffsklärung
Macht einfach mal auf irgendeine Datei auf der Festplatte rechte Maustaste --> Eigenschaften, Karteikarte Sicherheit. Um diesen Dialog geht es letzten Endes im Tutorial. Wir wollen die Möglichkeit haben, verschiedenen Benutzern/Gruppen verschiedene Sachen zu erlauben oder verbieten. In einem Beispiel werden wir z.B. die Möglichkeit haben zu regeln, WER einen Button drücken darf, und wer nicht.

Dieses komplette Fenster (Anhang: Editor.png) nennt sich "Access Control List", was wir nachfolgend ACL Editor nennen wollen. Jeder Benutzer oder jede Gruppe, die namentlich in der ACL aufgeführt ist, ist in Verbindung mit den erteilten Rechten jeweils ein "Access Control Entry" (ACE).

Genaugenommen ist diese ACL die "DACL". Es gibt noch die SACL, eine Liste vergleichbar der o.g. Liste, die man über "Erweitert" - "Überwachung" einsehen kann. Damit kann man z.B. einen Eintrag im Systemprotokoll auslösen, wenn jemand versucht die Firmendaten zu löschen. Mit dieser SACL beschäftigen wir uns NICHT.

Die SID ist die weltweit eindeutige Identifizierung eines Benutzerkontos oder einer Gruppe. Normalerweise versucht Windows immer den "menschenlesbaren" Namen der Benutzer und Gruppen darzustellen, wenn aber z.B. keine Verbindung zum Domänencontroller besteht, kann evtl. diese lange Zeichenfolge sichtbar sein. Die SID hat z.B. den Vorteil, dass man das Benutzerkonto oder die Gruppen umbenennen kann, ohne alle Berechtigungen neu vergeben zu müssen. Quasi ist sie der Primärschlüssel der Tabelle "Benutzer- und Gruppenkonten".

Die "Known-SID"s sind die bekannten, also auf allen Windows PCs identischen Benutzerkonten. Hier stellen die Units also Konstanten für die Gruppe "Gäste", "Administratoren" [Lokal], "Domänen-Admins", "Jeder" etc. bereit.

Alle Einstellungen, die man nun im ACL-Editor treffen kann, werden (zumindest programmiertechnisch) unter dem Begriff "Security Descriptor" (nachfolgend "SD" genannt, also "Sicherheitsbeschreibung") zusammengefasst. Das tolle ist, dass der SD auch als reiner String vorliegt, so dass man diesen komfortabel laden und speichern kann.

Los geht's
Ladet die JwSCL runter und entpackt die Dateien. Ich habe die aktuelle .zip z.B. nach C: entpackt und habe nun im Ordner "C:\JEDI API 2.3 and JEDI WSCL 0.9.3\jwscl\branches\0.9.3\source" alle benötigten Units. Diesen Pfad müsst Ihr bei Euren Projekten oder in Delphi generell als Suchpfad hinzufügen. Im schlimmsten Fall kopiert alle Dateien aus meinem Demo-Projekt in diesen Ordner hinein, dann solle es sich kompilieren lassen.

Startet das Demo-Projekt und macht Euch mit den Möglichkeiten vertraut. Erteilt Benutzern oder Gruppen Berechtigungen, oder verweigert einzelnen Benutzern ein bestimmtes Recht. Auch Verschachtelung (nur in Domäne) von Gruppen funktioniert.

Beispiel: ICH erhalte die Rechte 1 und 2, die Gruppe "Marketing", deren Mitglied ich bin das Recht 1 und 3. Ergebnis: Ich habe die Rechte 1,2,3.
Wird nun die Gruppe "Alle Mitarbeiter" mit dem Recht 4 hinzugefügt, deren einzige Mitglieder die Gruppen(!) "Marketing" und "Vertrieb" sind, habe ich nun alle 4 Rechte, da ich ja Mitglied in Marketing bin, und somit auch indirekt Mitglied in "Alle Mitarbeiter". Wenn man "Marketing" nun das Recht 1 auf verweigern setzt, habe ich nur die Rechte 2-3. Alles klar?

Bitte schaut Euch nun den Quelltext des Demo-Projekts an (siehe auch Unten), und fahrt dann hier fort.

LeseQuelltext;


Zum Quelltext: Wir arbeiten durchgehend mit dem SD "FmySecurityDescriptor". Dieser wird beim Programmstart erzeugt, und mit dem ACL-Editor bearbeitet. Damit dieses Windows-Fenster weiß, wie die Rechte heißen, müssen wir die Klasse TMyDemoMapping erstellen, die aus dem Array "DemoMapping" dann die Daten liefert.
Wird der Editor mit "Ok" geschlossen, wird der SD aktualisiert und als String in eine Text-Datei geschrieben (wird beim Programmstart wieder geladen).

Mittels TJwSecureGeneralObject.AccessCheck kann man nun prüfen, ob ausreichend Rechte vorhanden sind.

Anmerkungen
Ich hoffe, für den ersten Einstieg langen die Kommentare im Quelltext.
Anbei noch einige Anmerkungen, mit Sachen, die man wissen sollte:

1) Wie im Quelltext beschrieben, wird bei AccessCheck der "Desired Access" als dezimale Zahl einer Binär-Marke übergeben. Das bedeutet in der Binärzahl steht an der Stelle eine "1" (von Rechts nach Links), wo in der Rechteverwaltung (von Oben nach Unten), also dem ACL-Editor, ein "Erlauben" steht. Bitte beachtet, dass hier für die Berechnung natürlich gemeint ist, dass schon die Berechtigungen aller Gruppen addiert werden ("Marketing", "Alle Mitarbeiter", [Ich]) und dann auch wiederum die Rechte entzogen werden, wenn bei mir oder einer Gruppe bei einem Recht "verweigern" ausgewählt wurde.

Das Array "DemoMapping" verwendet bei "Right" wie ihr vielleicht bemerkt habt, die "PowerOf2" reihe, also ein Vielfaches von 2. Die Profis unter Euch sehen nun also direkt eine (längere) Binär-Zahl, bei der alle Bits "0" sind, außer einem, und das wandert mit jedem "Recht" eins weiter nach Links. Das bedeutet, dass wenn nachher alle Rechte -auch von allen Gruppen in denen Ihr seid- zusammengefasst werden, diese tatsächlich zusammen"gerechnet" werden. Es ergibt sich eine binäre Marke in der für jedes Recht wiederum "1" steht, wenn es erlaubt ist. Bei einem Array wie in diesem Beispiel mit 4 Einträgen, ist das maximale Recht als 15 (=1111 Binär). Siehe Anhang: Maske.png

Dieses Wissen ist für diese Demo und unsere -zunächst einfachen- Ziele vollkommen irrelevant. Vergebt die Rechte wie in meiner Demo und gut ist.

[Unwichtig für den Einstieg]
Als Hintergrundwissen ist aber vielleicht interessant: Bei der Verwaltung von Rechten anderer Objekte (z.B. Dateien!) gibt es Konstellationen, bei denen ein Recht ein anderes Recht erfordert bzw. erzwingt. Wenn man das Recht "löschen" bekommt, muss man zwangsläufig auch "schreiben" können.

Würde man im Demo-Mapping bei "Demo Recht 4" - "Right" auf 15 setzen, würde das bedeuten, dass in dem Standard-Dialog von Windows (dem ACL-Editor) automatisch ALLE Haken auf "erlauben" gesetzt werden, wenn man den Haken bei "Recht 4" anhakt. Die binäre Maske von 15 lautet "1111", d.h. "alle Haken müssen gesetzt sein". Würde man nun den Haken bei z.B. "Recht 3" rausnehmen, würde auch automatisch der Haken bei "Recht 4" verschwinden (weil Recht 4 erfordert, dass ALLE Haken gesetzt sind).

Macht man nun später mit AccessCheck die Abfrage, gilt identisch: Ich gebe eine Maske vor, welche Haken alle gesetzt sein müssen, damit "True" zurück kommt.

Der Einfachheit halber sollte das zunächst alle weggelassen werden: Jedes Recht belegt nur 1 Bit, und jede "Darf-ich-das" Abfrage fragt am einfachsten auch immer nur ein Recht ab.
[/Unwichtig für den Einstieg]

2) Das Tutorial bezieht sich absichtlich und explizit nur auf den Benutzer, der gerade unser Programm gestartet hat, da wir ja nur schauen wollen, ob er was darf oder nicht. Wer nun prüfen will ob ein anderer Benutzer das darf -damit man z.B. die Einstellungen Eures Programms betreten darf-, indem man die Anmeldedaten eines berechtigten Benutzers eingibt, muss sich selbst einlesen und darf es hier gerne posten. Technisch ist es möglich.

3) Der SD speichert PrimaryGroup und/oder Owner nicht als String mit ab? Deshalb muss ich die auch nach dem Laden über das Memo neu zuweisen, sonst gibt es eine Exception bei "AccessCheck"!

4) Für Internationalisierung / Lokalisierung: Jederzeit und/oder FormCreate kann man die Texte des Arrays "DemoMapping" natürlich durch die übersetzten Texte ersetzen lassen: DemoMapping[1].Name := 'Bla';

5) DemoMapping.Flags = SI_ACCESS_GENERAL bedeutet, dass die "Rechte" direkt im Editor angezeigt werden, ansonsten muss man auf "Erweitert" Klicken, um sie anzeigen/bearbeiten zu können.

6) Wenn Ihr mehr als 4 Rechte verwenden woll, erweitert auch das Array: DemoMapping: array[1..15]!

7) Verwendet nicht mehr als die ersten 15 Bits der Rechteverwaltung. Alles was darüber hinausgeht ist Windows-intern und Ihr macht Euch nur Probleme!

8) Wer mehr als 15 verschiedene Rechte benötigt, bitte nicht den Wald vor lauter Bäumen übersehen. Ihr könnt Euch unendlich viele Security-Descriptoren anlegen! Ihr könnt die Berechtigungen für jedes einzelne Objekt in Eurer Software einzeln festlegen (lassen vom Benutzer). Wenn Ihr z.B. eine Kundenverwaltung habt, macht man ein SD/Objekt für "Kundenkartei einsehen", "Kunden anlegen", "Kunden bearbeiten", "Kunden löschen", und ein SD/Objekt für "Rechnung schreiben", "Rechnung stornieren", ... Der Benutzer muss also im Endeffekt an mehreren Stellen Berechtigungen verteilen, aber das ist vielleicht besser, als alles auf diese max. 15 Rechte "herunterzubrechen" und nachher passt's dann doch nicht...

9) ACLEditor.Servername ermöglicht es einem, von einem bestimmten Server die SIDs in menschenlesbare Gruppen-/Benutzernamen umwandeln zu lassen. Für normale Zwecke unerheblich, auch in einer Domäne brauch man ihn nicht angeben.

10) Wenn die PrimaryGroup (oder was es Owner?) JwNullSID ist, darf JEDER - ALLES, wenn die ACL-Liste komplett leer ist.

11) Mit PrimaryGroup und Owner aufpassen: Wenn die Berechtigungen nicht passen, also die ACL-Liste leer ist, kann es sein, dass NIEMAND mehr die Berechtigungen anpassen darf. Sollte als zur Not auf (Domänen-)Administrator stehen??

12) Ihr könnt den SD natürlich auch ohne das GUI, also ohne den Windows-ACL-Editor manipulieren, z.B. mit
FmySecurityDescriptor.DACL.Add(TJwDiscretionaryAcc essControlEntryAllow.Create(nil, [afObjectInheritAce,afContainerInheritAce],GENERIC_ALL,JwWorldSID,false));
FmySecurityDescriptor.DACL.Items[0].AccessMask := 15;

Dies fügt den Eintrag "Jeder" (JwWorldSID) hinzu, und erlaubt ihm über die AccessMask die Rechte 1-4 (15 = Binär 1111). Achtung: Ich gehe hier davon aus, dass dies der erste Eintrag der Liste ist (Items[0]), bitte entsprechend berücksichtigen!). Vielleicht hat einer ein besseres Beispiel?

13) Auf Eurem lokalen PC können keine Gruppen verschachtelt werden (also "Marketing" und "Vertrieb" als Teil von "Alle Mitarbeiter" geht nicht!).

Nachwort
Wie erwähnt bin ich kein Profi im Bereich ACL und musste mir vieles selbst erarbeiten. Fachliche/Sachliche im Rahmen des Tutorial sind unter Umständen gewollt, um den Einstieg oder das Grundverständnis nicht durch unnötige Details zu erschweren. Ich versuche jedoch, alle Korrekturvorschläge umzusetzen.

Insgesamt möchte ich mich hier auch nochmal bei Dezipaitor bedanken, der uns die JwSCL überhaupt ermöglicht hat (er ist auch hier im Forum aktiv!), und natürlich bei Allen, die mich bei meinen Threads immer unterstützen, ich hoffe, ich konnte hiermit eine Kleinigkeit zurückgeben...


JEDI Windows Security Code Library (auch Download)
http://blog.delphi-jedi.net/security-library/

JWSCL Documentation
http://jwscldoc.delphi-jedi.net/

Delphi-Quellcode:
unit UMainForm;

interface

uses
  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,
  jwaWindows,
  JwsclTypes,
  JwsclAcl,
  JwsclMapping,
  JwsclKnownSid,
  JwsclSecureObjects,
  JwsclSecurityDialogs,
  JwsclDescriptor,
  JwsclStrings; //JwsclStrings, must be at the end of uses list!!!;




type
  TMyDemoMapping = class(TJwSecurityGenericMapping)
  public
    class function GetAccessNames(out iCount: Cardinal): PSI_ACCESS; override;
  end;

  TForm1 = class(TForm)
    btnRechteVerwalten: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    Button2: TButton;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    CheckBox5: TCheckBox;
    CheckBox6: TCheckBox;
    procedure btnRechteVerwaltenClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    FmySecurityDescriptor : TJwSecurityDescriptor;
    // Nicht fragen, einfach 1:1 kopieren
    procedure OnSetSecurity(Sender: TJwSecurityDescriptorDialog;
      SecurityType: TJwSecurityInformationFlagSet;
      SecurityDialogFlags: TJwSecurityDialogFlags;
      SecurityResetType: TJwSecurityResetTypes;
      Settings: TJwSecurityDescriptorControlSet;
      NewSecurityDescriptor, MergedSecurityDescriptor
      : TJwSecurityDescriptor;
      var bSuccess: boolean);

  public
    procedure InitializeDemoSD;
  end;

const
  DemoMapping: array[1..4] of TJwRightsMapping =
    (
    (Right: 1; Name: 'Demo Recht 1'; Flags: SI_ACCESS_GENERAL),
    (Right: 2; Name: 'Demo Recht 2'; Flags: SI_ACCESS_GENERAL),
    (Right: 4; Name: 'Demo Recht 3'; Flags: SI_ACCESS_GENERAL),
    (Right: 8; Name: 'Demo Recht 4'; Flags: SI_ACCESS_GENERAL)
// (Right: 16; Name: 'Demo Recht 5'; Flags: SI_ACCESS_GENERAL),
// (Right: 32; Name: 'Demo Recht 6'; Flags: SI_ACCESS_GENERAL),
// (Right: 64; Name: 'Demo Recht 7'; Flags: SI_ACCESS_GENERAL),
// (Right: 128; Name: 'Demo Recht 8'; Flags: SI_ACCESS_GENERAL),
// (Right: 256; Name: 'Demo Recht 9'; Flags: SI_ACCESS_GENERAL),
// (Right: 512; Name: 'Demo Recht 10'; Flags: SI_ACCESS_GENERAL),
// (Right: 1024; Name: 'Demo Recht 11'; Flags: SI_ACCESS_GENERAL),
// (Right: 2048; Name: 'Demo Recht 12'; Flags: SI_ACCESS_GENERAL),
// (Right: 4096; Name: 'Demo Recht 13'; Flags: SI_ACCESS_GENERAL),
// (Right: 8192; Name: 'Demo Recht 14'; Flags: SI_ACCESS_GENERAL),
// (Right: 16384; Name: 'Demo Recht 15'; Flags: SI_ACCESS_GENERAL)
    );


var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnRechteVerwaltenClick(Sender: TObject);
var ACLEditor : TJwSecurityDescriptorDialog;
    Mapping : TJwSecurityGenericMappingClass;
    bla: TJwSecurityGenericMappingClass ;
    Rechte, Test: Cardinal;
    r, t: string;
begin
  // Bitte dran denken: In den richtigen Projekten prüfen lassen, ob der Benutzer überhaupt die Rechte ändern darf!
  // Behaltet Euch also in der Liste einen Eintrag vor z.B. hier "Recht 1", das Ihr dann für "Berechtigungen ändern" oder
  // so verwendet.
  // Wenn "Bit 1", also Recht 1 nicht gesetzt ist, abbrechen
  // if not TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 1, TMyDemoMapping) then begin
  // ShowMessage('Keine Berechtigung, die Rechte zu ändern!');
  // Exit;
  // end;

  // Editor erzeugen
  ACLEditor := TJwSecurityDescriptorDialog.Create(GetActiveWindow);

  // Zum testen in dieser Demo erstmal Alles freischalten (Erweitert-Button, alle Karteikarten, etc.)
  ACLEditor.Flags := [sdfAdvanced, sdfEditDacl, sdfEditOwner, sdfEditEffective,
                       sdfNoAdditionalPermission, sdfEditSacl];
  // Caption des Dialogs, bzw. der "Objektes", für das gerade die Sicherheit verändert wird. Nehmt zur Not euren Programmnamen oder so...
  ACLEditor.ObjectName := 'Beschreibung des Sicherheitsdialog DEMO';
  // Nicht fragen, einfach 1:1 kopieren
  ACLEditor.ServerName := '';


  try
    // An dieser Stelle wird der SD neu erzeugt.
    // Das hat ist denke ich mal unnötig, denn ich habe mich damit noch nicht genug beschäftigt.
    // Das neu-erzeugen hat den Vorteil, dass wir nun die "Einstellungen", also alle Benutzer, Rechte, etc.,
    // also den kompletten SD "von Festplatte" laden können. Von der Festplatte ist ja schon geladen;
    // der SD liegt in Text-Form als String in "Memo1" vor. Diesen String wandeln wir nun mit dem
    // "Create"-Vorgang in einen gültigen SD um, auf den wir Quelltextmäßig zugreifen können.

    try
      // alten SD löschen
      FreeAndNil(FmySecurityDescriptor);
      // Wenn der SD in Textform vorliegt, diesen laden, ansonsten einen Leeren neu erzeugen
      if trim(Memo1.Text) <> 'then begin
        FmySecurityDescriptor := TJwSecurityDescriptor.Create(Memo1.Text);
      end else begin
        FmySecurityDescriptor := TJwSecurityDescriptor.Create;
      end;
      // Standardeinstellungen dieser Demo laden
      InitializeDemoSD;
    except
      // Gibt es hier eine Exception, steht in Memo1 ungültiger Kram drinnen. Also dann Memo1.Text löschen, oder
      // den SD in Text-Form neu generieren lassen (hier im Beispiel nicht gezeigt).
    end;

    // Nicht fragen, einfach 1:1 kopieren
    ACLEditor.OnSetSecurity := OnSetSecurity;

    // Hier wird auf die KLASSE verwiesen, welche die Namen etc. unserer "Rechtverwaltung" bereitstellt
    ACLEditor.Mapping := TMyDemoMapping;

    // Der Editor hat eine eigene SD Variable, die wir natürlich erstmal mit unseren aktuellen Einstellungen
    // füttern müssen. Assign bedeutet soviel wie, die komplette Variable zu kopieren. ":=" sollte hier NICHT verwendet werden.
    ACLEditor.SecurityDescriptor.Assign(FmySecurityDescriptor);

    // Editor anzeigen. Das Programm pausiert, bis der Dialog geschlossen wird.
    // Wenn der Dialog mit "Ok" beendet wurde:
    if ACLEditor.ShowModal then
    begin
      // Den kompletten SD wieder in unsere Variable zurückkopieren
      FmySecurityDescriptor.Assign(ACLEditor.SecurityDescriptor);
      // Den SD in Textform anzeigen lassen im Memo1 anzeigen lassen
      Memo1.Text := ACLEditor.SecurityDescriptor.GetSecurityDescriptorString(JwAllSiFlags);
      // WICHTIG: Hier könnt Ihr nun diesen String -also den kompletten SD in Textform- in Eure Datenbank oder
      // was auch immer abspeichern!
      Memo1.Lines.SaveToFile('MeineDemo.txt');
    end;

  finally
    ACLEditor.Free;
  end;

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
begin
  // Den SD in fast menschenlesbarer Form im Memo2 anzeigen lassen, nur für die Demo -zum zeigen- interessant
  Memo2.Text := FmySecurityDescriptor.Text;

  // Anzeigen, ob wir die Berechtigung für das Recht 1-4 haben
  // Dafür verwenden wir die Klassenfunktion TJwSecureGeneralObject.AccessCheck
  // Natürlich müssen wir übergeben, von welchem SD wird geprüft haben wollen, ob
  // der aktuelle Benutzer (Parameter 2 = NIL!) da Rechte drauf hat.
  // Deshalb übergeben wir hier FmySecurityDescriptor
  // Das TMyDemoMapping (Klasse, keine Instanz!) muss (leider) auch übergeben werden, "weshalb",
  // dazu kommen wir in einem späteren Tutorial)
  // Der dritte Parameter "Desired Access" (nachfolgend DA genannt) ist im Prinzip der wichtigste: Er gibt eine Binäre Maske an,
  // um der Funktion AccessCheck zu Zeigen, welche Berechtigungen bzw. "Haken" im ACL-Editor
  // für den aktuell angemeldeten Windows-Benutzer gesetzt sein MÜSSEN, damit als Ergebnis "True" zurück
  // geliefert werden kann.
  // Die Mitgliedschaft deines aktuellen Benutzers in mehreren Gruppen die hier aufgeführt sein können,
  // wird natürlich berücksichtigt!

  // Beispiel:
  // Öffnet den ACL-Editor (btnRechteVerwalten), wählt einen Benutzer/Gruppe aus,
  // Screenshot von den Editor machen, in Bilverarbeitungsprogramm 90° im Uhrzeigersinn drehen.
  // Die Haken für "Erlauben" (abzüglich der Haken bei "Verweigern") bilden nun eine Binärzahl. Siehe Wikipedia.
  // Haken = 1, Kein Haken oder Verweigert = 0, gelesen wird von Rechts nach Links (als Recht 1 ganz Rechts)
  // DA 0101 bedeutet also, Recht 1 UND 3 müssen vorhanden sein, also übergibt man die Dezimalzahl 5 (=Binär 0101)
  // DA 1010 bedeutet also, Recht 2 UND 4 müssen vorhanden sein, also übergibt man die Dezimalzahl 10 (=Binär 1010)
  // DA 0100 bedeutet also, (nur) Recht 3 muss vorhanden sein, also übergibt man die Dezimalzahl 4 (=Binär 0100)

  CheckBox1.Checked := TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 1, TMyDemoMapping);
  CheckBox2.Checked := TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 2, TMyDemoMapping);
  CheckBox3.Checked := TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 4, TMyDemoMapping);
  CheckBox4.Checked := TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 8, TMyDemoMapping);
  CheckBox5.Checked := TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 5, TMyDemoMapping);
  CheckBox6.Checked := TJwSecureGeneralObject.AccessCheck(Form1.FmySecurityDescriptor, NIL, 15, TMyDemoMapping);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Nicht fragen, einfach 1:1 kopieren
  JwInitWellKnownSIDs;

  // Einstellungen von Festplatte laden. Nur für dieses Beispiel interessant
  if FileExists('MeineDemo.txt') then begin
    Memo1.Lines.LoadFromFile('MeineDemo.txt');
  end;

  // Wenn der SD in Textform vorliegt, diesen laden, ansonsten einen Leeren neu erzeugen
  if trim(Memo1.Text) <> 'then begin
    FmySecurityDescriptor := TJwSecurityDescriptor.Create(Memo1.Text);
  end else begin
    // den SD erzeugen, damit er immer gültig ist, wenn wir drauf zugreifen
    FmySecurityDescriptor := TJwSecurityDescriptor.Create;
  end;
  // Prozedur dieser Demo, um den SD immer mit den selben Optionen zu betreiben, wenn er neu erstellt wird
  InitializeDemoSD;

  Memo2.Text := FmySecurityDescriptor.Text;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FmySecurityDescriptor);
end;

procedure TForm1.InitializeDemoSD;
begin
  // JwNullSID = Keine (Primäre) Grupp / Niemand
  FmySecurityDescriptor.PrimaryGroup := JwNullSID;
  // JwWorldSID = JEDER darf zunächst die Einstellungen der Rechte ändern
  FmySecurityDescriptor.Owner := JwWorldSID;
end;


// Diese Prozedur einfach 1:1 übernehmen, ohne sie funktioniert der ACL Dialog nicht!
procedure TForm1.OnSetSecurity(Sender: TJwSecurityDescriptorDialog;
  SecurityType: TJwSecurityInformationFlagSet;
  SecurityDialogFlags: TJwSecurityDialogFlags;
  SecurityResetType: TJwSecurityResetTypes;
  Settings: TJwSecurityDescriptorControlSet; NewSecurityDescriptor,
  MergedSecurityDescriptor: TJwSecurityDescriptor; var bSuccess: boolean);
begin
  bSuccess := true;
end;

// Callback-Funktion, die es dem Windows-Standard-Dialog erlaubt, unsere
// benutzerdefinierten "Namen" für die einzelnen Rechte zu laden; "Demo-Recht 1-4" in diesem Beispiel.
class function TMyDemoMapping.GetAccessNames(out iCount: Cardinal): PSI_ACCESS;
begin
  Result := GetAccessNamesEx(iCount, DemoMapping);
end;

end.
Miniaturansicht angehängter Grafiken
editor.png   maske.png  
Angehängte Dateien
Dateityp: zip Demo1.zip (904,8 KB, 45x aufgerufen)
 
Themen-Optionen Tutorial durchsuchen
Tutorial durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:18 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz