|
Registriert seit: 3. Sep 2004 441 Beiträge Delphi 10.4 Sydney |
#1
Hallo zusammen!
Ich bilde mir ein schon die Suchfunktion genutzt zu haben, aber konnte leider keine Einsteiger-Freundlichen Infos erhalten, womit ich aktuell sinnvoll etwas anfangen könnte. Das will ich in etwa machen: Siehe Anhang. Ziel ist es, -mit dem Sicherheitssystem von Windows- die Benutzer/Gruppen von Windows (bei Einzelsystemen) bzw. ActiveDirectory in Domänen für bestimmte Funktionen in meinem Programm zu berechtigen bzw. zu sperren. So dürfen dann beispielsweise alle Personen einer Gruppe das Programm starten und Daten betrachten, bestimmte Benutzer allerdings nur Daten verändern oder löschen. Es gelten die üblichen Bedingungen (und Einschränkungen): Benutzer dürfen das Programm auch dann starten, wenn Sie nicht namentlich in [meiner] Liste aufgeführt sind, sondern auch wenn Sie Mitglieder in einer oder mehrerer Gruppen sind, die diese Berechtigung haben. Das Sicherheitssystem von Windows (Zumindesten in Bezug auf die Sicherheitsrechte von Dateien und Registry-Keys) sollte den Meisten hier bekannt sein. Da mir das auf API-Ebene alles zu abstrakt ist verwendet ich die "Security Library" der Jedi-Komponenten: ![]() Bisherige, unter anderem verwendete Websites: ![]() ![]() ![]() Leider ist es so, dass man mit der bei Jedi mitgelieferten Dokumentation nirgendwo "einsteigen" kann. Dort wird stets nur in Abkürzungen gesprochen und direkt auf der Startseite gesagt nach dem Motto "Ihr müsst euch mit dem Windows-Sicherheitssystem auskennen, um die Komponente nutzen zu können." Hmja... Ohne Einstiegspunkt kann man sich das schlecht beibringen... In dem o.g. Tutorial zum Sicherheitsdialog wird zwar schön beschrieben, wie man die Zugriffsrechte von Dateien ändern kann, aber leider nicht, die das mit einem eigenen Objekt geht. Klären wir vielleicht zunächst mal die Terminologie, korrigiert mich, wenn ich falsch liege: DACL (discretionary access control list) Ist letztendlich die Liste mit allen Benutzern und allen Rechten (und "Verweigerungen") für das Objekt, die Datei oder den Registrykey. ACE (Access control entry) Ist EIN Eintrag in der DACL, also z.B. "Gruppe A" darf die Datenbank bearbeiten oder "Gruppe Leiharbeiter" wird Bearbeiten verweigert. Eine DACL darf beliebig viele ACEs enthalten. Wenn Benutzer "Alice" nun in "Gruppe A" ist, darf Sie also damit auch automatisch die Datenbank bearbeiten, es sei denn, Sie ist zusätzlich|stattdessen Mitglied in "Gruppe Leiharbeiter". Korrektur: ACE ist ein RECHT, das immer nur für den aktuell ausgewählen Benutzer/Gruppe bearbeitet werden kann (z.B. "Lesen" oder "Schreiben")? ACLEditor Das Programm/Fenster aus dem Screenshot (siehe Anhang). Kann nativ über die Windows-API "EditSecurity(GetActiveWindow, Self)" aufgerufen werden. Vorgehensweise: Anhand eines Beispiels der Jedi-Komponenten habe ich mich zunächst für die "StringDescriptor"-Demo entschieden: rein optisch kommt diese meinem Vorhaben am Nächsten. Der ACL Editor wird vorbereitet
Delphi-Quellcode:
Erzeugen der Instanz des Editors, setzen der Flags (welche Buttons sollen sichtbar sein, etc.) und der Titelleiste des Editors.
ACLEditor := TJwSecurityDescriptorDialog.Create(GetActiveWindow);
// ACLEditor.Flags := [sdfAdvanced, sdfEditDacl, sdfEditOwner, sdfEditEffective, // sdfNoAdditionalPermission, sdfEditSacl]; ACLEditor.Flags := [sdfEditSacl]; ACLEditor.ObjectName := 'Beschreibung des Sicherheitsdialog DEMO'; ACLEditor.ServerName := ''; Für die Demo: Erzeugen von ein paar ACEs, damit schon mal ein paar Leute Berechtigungen haben, wenn wir mit der GUI vom Editor rumspielen:
Delphi-Quellcode:
Die Gruppe "Gäste" [meines PCs --> "JwGuestsSID"] darf alles machen, "Jeder" (JwWorldSID) darf nur lesen, und "SYSTEM" (JwLocalSystemSID) darf (nur) schreiben. Soweit so gut. Die Thematik der SIDs verstehe ich und soll hier nicht unnötiger Weise (?) näher beleuchtet werden. Parameter 3+4 habe ich also verstanden, der Rest ist noch eher unklar.
SecurityDescriptor := TJwSecurityDescriptor.Create;
SecurityDescriptor.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,[],GENERIC_ALL,JwGuestsSID,True)); SecurityDescriptor.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,[],GENERIC_READ,JwWorldSID,false)); SecurityDescriptor.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,[],GENERIC_WRITE,JwLocalSystemSID,false)); ACLEditor.SecurityDescriptor := SecurityDescriptor; // das Editor-GUI soll nun also ^-- diese Liste bearbeiten Nach dem Ausführen des Editors (if ACLEditor.ShowModal then) kann ich das Objekt SecurityDescriptor durchgehen und alle Einträge auslesen. Wenn ich das richtig Verstanden habe, kann ich mir mit Memo1.Text := ACLEditor.SecurityDescriptor.GetSecurityDescriptorString(JwAllSiFlags) ; diese komplette DACL als String zurückgeben lassen, in dem alle zugelassenen/verweigerten Benutzer(-SIDs) stehen, sowie die Berechtigungen, so dass ich diese z.B. in meiner Datenbank speichern, und beim nächsten Programmstart wieder auslesen kann (?). Nur kommt der Punkt, an dem ich hänge: Wie weise ich dem Dialog "zeilenweise" die Rechte zu, die der Benutzer bearbeiten können soll? Als Optionen sollen nur "Zulassen" und "Verweigern" verwendet werden. (Oder nur "Zulassen", wenn das wesentlich einfacher ist.) In der o.g. Demo "StringDescriptor" wird folgendes für diese zeilenweisen Rechte verwendet:
Delphi-Quellcode:
ComboBoxMapping.Items.Objects[ComboBoxMapping.ItemIndex] bezieht sich hier in der Demo natürlich auf ein Objekt in einer ComboBox, die beim Programmstart befüllt wurde:
Mapping := TJwSecurityGenericMappingClass(ComboBoxMapping.Items.Objects[ComboBoxMapping.ItemIndex]);
ACLEditor.Mapping := Mapping; // zuweisung der o.g. Rechte an den Editor/GUI
Delphi-Quellcode:
Hier wird also EIN Pointer auf eine KLASSE (nicht ein instanziertes Objekt!) übergeben, welche -abgeleitet von TJwSecurityGenericMapping- die Klassen-Funktionen "GetMapping", "MapAccessMaskToString" und "GetAccessNames" bereitstellt. Je nach verlinkert Klasse sind in dem Editor also andere ACE-Zeilen zu sehen.
ComboBoxMapping.Items.AddObject('Generic',Pointer(TJwSecurityGenericMapping));
ComboBoxMapping.Items.AddObject('Process',Pointer(TJwSecurityProcessMapping)); ComboBoxMapping.Items.AddObject('Threads',Pointer(TJwSecurityThreadMapping)); ComboBoxMapping.Items.AddObject('Service',Pointer(TJwSecurityServiceMapping)); ComboBoxMapping.Items.AddObject('FileFolder',Pointer(TJwSecurityFileFolderMapping)); Der DACL-Editor kann sich also über diese Callback-Funktionen ein Kontanten/Konstantes(?) Array holen, in dem die einzelnen Zeilen (ACEs?) stehen. Beispiel für Datei/Ordner-Sicherheit im Windows-Explorer:
Delphi-Quellcode:
Angenommen ich leite diese Klasse ab und erstelle mein statisches eigenes Array, sollte das ja dann klappen?
FileFolderMapping: array[1..19] of TJwRightsMapping =
( (Right: FILE_ALL_ACCESS; Name: 'Full control'; Flags: SI_ACCESS_GENERAL or SI_ACCESS_SPECIFIC), (Right: FILE_GENERIC_READ or FILE_GENERIC_WRITE or FILE_GENERIC_EXECUTE or Delete; Name: 'Modify'; Flags: SI_ACCESS_GENERAL or SI_ACCESS_SPECIFIC), (Right: FILE_GENERIC_READ or FILE_GENERIC_EXECUTE; Name: 'Read and execute'; etc. Die Frage ist nun halt auch noch, wie werden diese Werte abgespeichert, bzw. um was genau muss ich mich kümmern. Der DACL-Editor scheint ja selbst eine "Bit-Maske" zu erwarten, die er dann für jeden Benutzer/Gruppe füllen kann mit den Berechtigungen. Wie geht man das am schlausten an? Wofür braucht der Editor ACLEditor.OnSetSecurity := OnSetSecurity; In der Demo wird kommentarlos in OnSetSecurity die var-Variable bSuccess := true gesetzt... Letztendlich: Wie prüfe ich, ob Benutzer "Alice" (bzw. deren SID) das Recht "Datenbank bearbeiten" hat, wenn in der DACL nur "Gruppe A" und "Gruppe Leiharbeiter" aufgeführt sind? (Annahme: Alice ist Mitglied in Gruppe A) Vielen Dank im Voraus, vielleicht hilft mein Beitrag auch mal jemand anderem... Edit1: Scheinbar geht es auch ohne das Konstanten-Array. Seine eigenen Berechtigungen kann man erstellen, indem man von TJwSecurityGenericMapping eine Klasse ableitet und bestimmte Funktionen überschreibt:
Delphi-Quellcode:
Die "GetMapping" Prozedur soll in der abgeleiteten Klasse unbedingt überschrieben werden. Warum?
type
TMySampleMapping = class(TJwSecurityGenericMapping) public class function GetMapping: TGenericMapping; override; class function GetBitMappingString(Idx: Cardinal): TJwString; override; end; class function TMySampleMapping.GetBitMappingString(Idx: Cardinal): TJwString; begin case idx of 0: Result := 'Programm starten'; // Zeile 1 im ACL-Editor 1: Result := 'Daten schreiben'; // Zeile 2 else Result := 'DEMO ' + IntToStr(Idx); // Alle weiteren Zeilen, max. 32 insgesamt. end end; class function TMySampleMapping.GetMapping: TGenericMapping; begin Result.GenericRead := READ_CONTROL or STANDARD_RIGHTS_READ; Result.GenericWrite := WRITE_DAC or WRITE_OWNER or Delete or ACCESS_SYSTEM_SECURITY or STANDARD_RIGHTS_WRITE; Result.GenericExecute := STANDARD_RIGHTS_EXECUTE or SYNCHRONIZE; Result.GenericAll := Result.GenericRead or Result.GenericWrite or Result.GenericExecute; end; //Im Hauptprogramm: Mapping := TJwSecurityGenericMappingClass(Pointer(TMySampleMapping)); ACLEditor.Mapping := Mapping; Edit2: So kann man die im Dialog eingestellten Optionen laden/speichern:
Delphi-Quellcode:
// Speichern:
if ACLEditor.ShowModal then // Dialog ausführen, und wenn mit "Ok" beendet: begin // Einstellungen/Auswahl in einem String speichern (hier: Memo1.Text) // diesen String kann man nun z.B. in der Datenbank speichern! Memo1.Text := ACLEditor.SecurityDescriptor.GetSecurityDescriptorString(JwAllSiFlags); end; // Laden: // hier muss der vorher gespeicherte Wert schon fertig drinnen geladen sein, sonst gibts Exception! SecurityDescriptor := TJwSecurityDescriptor.Create(Memo1.Text); ACLEditor.SecurityDescriptor := SecurityDescriptor; Geändert von berens (23. Apr 2015 um 11:31 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |