WindowsAuthentication und Datasets

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von ruediger_006.

    WindowsAuthentication und Datasets

    Hallo!

    Ich möchte folgendes umsetzen.

    Ich habe Mitarbeiterdaten auf einem SQL-Datenbankserver (Name, Geburtsdatum und Lohn) . Alle Mitarbeiter sollen mittels
    eines VB.Net Programms ihre Daten einsehen und ändern können. Die Anmeldung auf den Server erfolgt per Windows-Authentication. (Ich arbeite mit Datasets).

    Das einloggen funktioniert schonmal :) Jetzt muss ich es aber so hinbekommen, dass beim öffnen
    des Programms nur die Informationen des Mitarbeiters angezeigt werden, der sich eingeloggt hat.Und wenn er Daten in die Datenbank schreibt, diese
    unter seiner ID gespeichert werden.
    Jetzt haben aber verschiedene Mitarbeiter verschiedene Rechte. Bspw. kann ein Abteilungsleiter alle Daten
    seiner Abteilungsangehörigen sehen, aber nicht der anderen Mitarbeiter.

    Ich werde wohl falsch suchen, ich finde aber bei google nichts, was mir dabei wirklich weiterhilft.

    Hat jemand vielleicht einen Tip, wie ich mich da am besten einarbeiten kann. Vielleicht kennt jemand ein Tutorial oder so.

    Herzlichen Dank schonmal!
    @StormySunshine:: Es ist ja schön, dass du die Worte von ErfinderDesRades rezitierst. Jetzt müsste das an dieser Stelle nur noch sinnvoll sein...

    @ruediger_006:: Solche Berechtigungen werden üblicherweise in der Datenbank gesetzt, nicht im Frontend. Jeder Benutzer bekommt nur das zu sehen, was er soll, indem du Views in der DB definierst und die Berechtigungen darauf einschränkst. Beispiel:

    Tabelle Mitarbeiter (ID, Status, Division, FName, LName, Salary):
    1, Boss, Vorstand, Fritz, Müller, 100000€
    2, Sekretärin, Buchhaltung, Mia, Muster, 35000€
    26, AbtLeiter, Entwicklung, Paul, Meier, 75000€
    27, Arbeiter, Entwicklung, Tim, Schmidt, 40000€
    28, AbtLeiter, Personal, Sonja, Lehmann, 80000€

    SQL-Abfrage

    1. CREATE VIEW AbtEntwicklung AS (SELECT * FROM Mitarbeiter WHERE Division = 'Entwicklung');
    2. CREATE VIEW AbtPersonal AS (SELECT * FROM Mitarbeiter WHERE Division = 'Personal');
    3. etc...


    Berechtigungen:
    Boss: Alles
    ID=28: AbtPersonal
    ID=26: AbtEntwicklung

    Das Frontend (VB-Programm) besteht nur noch aus einem Menü, in dem alle Views drinstehen, und irgendwas zur Anzeige. Beim Abruf eines Views werden als Benutzerdaten die aktuellen Windows-Credentials mitgesendet. Die Datenbank kümmert sich dann darum, ob die Anfrage berechtigt ist oder nicht, was im Programm entsprechend angezeigt wird. Damit hast du schonmal alle Führungskräfte und Abteilungsleiter erschlagen - die haben über ihre Abteilungs-Views nun Zugriff auf die DB.

    Alle Mitarbeiter sollen mittels eines VB.Net Programms ihre Daten einsehen und ändern können.
    Es erscheint mit nicht sinnvoll, dass ein Mitarbeiter seinen Namen, sein Geburtsdatum und seinen Lohn selbst ändern kann, deshalb höre ich mal bei den Abteilungsleitern auf zu denken und frage lieber nochmal nach. Also: Was soll das?
    Gruß
    hal2000
    Hallo HAL2000!

    Super gut!!! Danke für deine Antwort.

    Zu den Views im Rahmen von Datasets habe ich noch eine Frage. Wenn ich in der Datenbank ein View erstelle (das Felder aus 3 Tabellen hat die m:n und 1:n Relationen haben) und das View dann in ein Dataset lade welches ich in an ein Datagrid binde, kann dann der User in dem Datagrid Änderungen vornemen, die dann über update zurückgespielt werden können?? Funktionieren denn Datasets mit Views einwandfrei? Frag mich jetzt nicht wo, aber ich meine gelesen zu haben, dass Datasets probleme beim Updaten von "Join" haben und in meinem View wären ja "Joins" drin. Oder ist das kein Problem, wenn die Views schon auf dem Server liegen?

    Das einsehen und ändern bezog sich auf das folgende Problem:
    Also im großen und ganzen handelt es sich um eine Art Arbeitszeit Festhaltung. Jeder Mitarbeiter kann seine eigenen Zeiten sehen und diese auch nachträglich ändern. Jeder Mitarbeiter soll aber nur seine eigenen Zeiten einsehen können. Da jeder Mitarbeiter ja eine ID (in der DB) hat und seine WindowsAnmeldename in die Datenbank eingetragen wird und mit dieser verbunden ist, muss das darüber zu lösen sein (denke ich). Meine Idee dazu, ich fange den Namen (der sich in einer Domäne befindet) des Mitarbeiters mit VB ab und hole mir die MitarbeiterID. Abhängig von dieser muss ich dann ein View erstellen das angezeigt wird und welches der Mitarbeiter dann verändern kann (ist die Überlegung von mir so richtig??). ABer kann man das so mit Datasets überhaupt umsetzen? Die Views müssten dann aber aus VB heraus erstellt werden, weil ich ja nicht für jeden neuen Mitarbeiter in der DB einen neuen View erstellen möchte. Da schließt sich natürlich der Kreis mit dem o.g. Viewsproblem.

    VG und danke nochmal für den Tip oben!!

    Ruediger
    Hi,

    ruediger_006 schrieb:

    kann dann der User in dem Datagrid Änderungen vornemen, die dann über update zurückgespielt werden können?
    Das geht nur, wenn das View eine 1:1-Beziehung zu einer darunterliegenden Tabelle hat, was bei dir nicht der Fall ist.

    ruediger_006 schrieb:

    Funktionieren denn Datasets mit Views einwandfrei?
    Ja - ein View ist in der Datenbank definiert und wird wie eine normale Tabelle abgefragt. Der Abfragende weiß nicht, dass er nur eine extra für ihn zusammengestellte Tabelle bekommt - das macht die DB transparent.

    ruediger_006 schrieb:

    ich meine gelesen zu haben, dass Datasets probleme beim Updaten von "Join" haben und in meinem View wären ja "Joins" drin.
    Das liegt nicht am Dataset, sondern am Join im View. Vergleiche z.B. MySQL: dev.mysql.com/doc/refman/5.0/en/view-updatability.html

    ruediger_006 schrieb:

    Abhängig von dieser muss ich dann ein View erstellen das angezeigt wird und welches der Mitarbeiter dann verändern kann (ist die Überlegung von mir so richtig??).
    Das wäre nicht sinnvoll, denn damit hätte jedes View nur einen einzigen Datensatz (nämlich den des anfragenden Mitarbeiters). Die Views sind eher für die Abteilungsleiter gedacht, die dann aber wie oben festgestellt keine Änderungsmöglichkeit haben. Vergiss also die Views, wenn du was ändern musst.

    Sicherheitstechnisch gesehen ist es anzuraten, dass die DB einem User nur die Daten ausliefert, die er auch sehen und ggf. ändern darf. Wenn du garantieren kannst, dass das Programm nicht kompromittiert wird, kannst du die DB auch die ganze Tabelle liefern lassen und den Zugriff im Programm beschränken. Davon rate ich aber ab - lass das die DB machen, die kann das besser. Außerdem kannst du so den Datenverkehr im Netzwerk drücken, weil nicht die ganze Tabelle übertragen wird.

    Du könntest zwei Stored Procedures schreiben und allen Mitarbeitern darauf Zugriff gewähren (aber nicht auf die Tabelle). Die erste ist für SELECT und liefert die Datensätze für den aktuellen User zurück. Im SQL Server (sofern du den benutzt) bekommst du den aktuellen User mit

    SQL-Abfrage

    1. SELECT SUSER_NAME()

    In VB kannst du die Abfrage dann so einbinden (füge deine Windows-Authentifizierung noch hinzu):
    stackoverflow.com/questions/19…-procedure-to-a-datatable

    Die zweite SP ist für UPDATE, sucht sich ebenfalls den aktuell angemeldeten Nutzer und nimmt als Parameter den zu ändernden Datensatz. Wenn die UserID im Datensatz der Tabelle zum aktuellen Nutzer passt, wird die Änderung vorgenommen, sonst wird sie abgelehnt. Das kannst du mit deiner Verbindung zwischen Windows-Name und UserID prüfen, die du oben genannt hast.
    Gruß
    hal2000
    Hi HAL!

    Erstmal herzlichen Dank für die Hilfe! Ich mache das zum ersten mal und über die Sicherheitsproblematik hatte ich gar nicht nachgedacht. Die erste stored Procedure steht jetzt auch schon.
    Wenn ich ein Dataset hinzufüge und dann den DataAdapter konfiguriere kann ich ja auch "vorhandene gespeicherte Prozedur" auswählen. Im nächsten Dialog kann ich dann bei Select, Insert und Update meine Prozedur auswählen. Wenn ich das machen und dann die Tabelle in meine Form ziehe und das Prog kurz anteste, kommen auch nur die Daten von einem User.
    Funktioniert das so auch oder soll ich die Abfrage lieber nach deinem Link einbinden also manuell?

    Beste Grüße!

    und falls jemand mal das gleiche Problem haben sollte, hier mein Code für die erste Stored Procedure:

    Quellcode

    1. CREATE PROCEDURE BenutzerTabelle as
    2. --set parameters
    3. DECLARE @TEMPUSER_ID as int
    4. DECLARE @MyDomainLogin varchar(30)
    5. --SUSER_NAME returns DOMAIN\USERNAME, since we only stored the Username in the Database
    6. --the following code cuts the Domain part off.
    7. BEGIN
    8. SET @MyDomainlogin = SUSER_NAME()
    9. SET @MyDomainLogin = SUBSTRING(@MyDomainLogin,CHARINDEX('\',@MyDomainLogin) + 1,30)
    10. --Select only userspecific entries from a table (in this case the 'Table1' Table)
    11. SELECT @TEMPUSER_ID = workers_ID FROM WorkersTable
    12. WHERE WindowsUserName = @MyDomainLogin
    13. SELECT * FROM Table1
    14. WHERE workers_ID = @TEMPUSER_ID
    15. END

    ruediger_006 schrieb:

    Die erste stored Procedure steht jetzt auch schon.
    Genau so hatte ich mir das vorgestellt :). Schön, dass du deine Erkenntnisse teilst (das machen leider nicht alle).

    ruediger_006 schrieb:

    Funktioniert das so auch oder soll ich die Abfrage lieber nach deinem Link einbinden also manuell?
    Du kannst auch den Assistenten benutzen. Der ist gleichwertig zu meiner verlinkten Variante, nur mit dem Unterschied, dass alles im Hintergrund generiert wird. Das ist solange kein Problem, wie keine Fehler auftreten. Wenn dann aber mal was schiefgeht, sitzt du vor einer Blackbox mit bunter Oberfläche, die du nur schwer debuggen kannst. Naja nicht ganz: Den generierten Code kannst du dir anschauen (und vielleicht auch debuggen), wenn du im Projektexplorer alle Dateien anzeigen lässt und das DataSet aufklappst. Die Datei [Name].Designer.vb enthält den Code.

    Edit: Du kannst die Prozedur auch noch für die Abteilungsleiter aufbohren, sodass die alle Mitarbeiter bekommen, die unter ihnen arbeiten. Idee dazu:

    SQL-Abfrage

    1. SELECT @TEMPUSER_ID = workers_ID FROM WorkersTable
    2. --Falls du irgendwo ein Status-Feld hast
    3. SELECT @TEMPUSER_STATE = workers_status FROM WorkersTable
    4. IF (@TEMPUSER_STATE == 'Abteilungsleiter')
    5. BEGIN
    6. SELECT @ABTEILUNG = [Abteilungsfeld] FROM [Tabelle mit Führungskräften und Verantwortlichkeiten] WHERE userID = @TEMPUSER_ID
    7. -- Alle Mitarbeiter der Abteilung und der eigene Datensatz
    8. SELECT * FROM Table1
    9. WHERE [Abteilungsfeld] = @ABTEILUNG
    10. END
    11. ELSE
    12. BEGIN
    13. -- Nur der eigene Datensatz
    14. END

    Ich kenne deine DB nicht, aber ich denke du weißt, was in etwa gemeint ist.
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hal2000“ ()

    Hi!

    Super Idee, so wirds gemacht!

    Ich bastel nun schon etwas länger an der Update Prozedur, die läuft jetzt auch ohne Fehlermeldung durch, updatet aber nichts :( Meinste du, du könntest nochmal bitte kurz drüber gucken.

    Ich habe die beim erstellen wieder den TableAdapter reingezogen und dann bei dem DropDown-Menu unter Update die folgende Prozedur ausgewählt.
    Die Benutzerspezifikation habe ich erstmal zum testen weggelassen.

    SQL-Abfrage

    1. CREATE PROCEDURE up_BenutzerTabelle1 as
    2. SET NOCOUNT ON
    3. DECLARE @StartZeit datetime
    4. DECLARE @EndZeit datetime
    5. ...
    6. BEGIN
    7. UPDATE Table1
    8. SET
    9. StartZeit = @StartZeit,
    10. EndZeit = @EndZeit
    11. ...
    12. END
    13. GO


    Diesen Code hat er produziert:

    VB.NET-Quellcode

    1. Private Sub BenutzerTabelleBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs) Handles BenutzerTabelleBindingNavigatorSaveItem.Click
    2. Me.Validate()
    3. Me.BenutzerTabelleBindingSource.EndEdit()
    4. Me.TableAdapterManager.UpdateAll(Me.DataSet1)
    5. End Sub


    Beste Grüße

    Ruediger
    woher weißt du, dass deine StoredProc ühaupt aufgerufen wird? Sieht mir nicht so aus, denn da sollte ein Fehler kommen.

    Ich wunder mich auch, dass Hal2000 von Create View spricht, du aber von Create Procedure. Ich habe Zweifel, ob MySql-Views dasselbe sind wie SqlServer.StoredProcedures.

    Ein View scheint ReadWrite sein zu können, während eine StoredProc entweder readed oder writet.
    Guten Morgen Erfinder!

    Ja, zuerst hatte mir HAL die Create View Lösung empfohlen als es lediglich um eine nichtbearbeitbare Datagridview ging. Im weiteren Verlauf hatten sich für eine andere Problematik aber die stored procedures empfohlen
    HAL2000: Du könntest zwei Stored Procedures schreiben
    Da bin ich gerade dabei. Die Select-Anweisung steht auch, aber ich komme mit der Update-Anweisung nicht weiter. 1. Wenn ich die Anweisung im TableAdapter Configuration Wizard unter Update einlade, stehen richts in dem Fenster keine Parameter denen ich was zuweisen kann. 2. Bin ich mir einfach nicht sicher, ob die Anweisung so richtig ist. Anscheinend nicht :S

    Ich habe die Update-Anweisung vorher ja auf dem Server als Stored Procedure erstellt, wobei erst ein paar Fehler gekommen sind und dann nach ein bisschen Feinschliff keine mehr. Deshalb habe ich geschrieben, dass sie durchläuft. Wenn ich den Wizard einfach ohne Parameterangabe durchklicke (meine Theorie war, dass für jeden Table die Spalten als @Spaltenname per se erstellt werden, weshalb ich sie nicht angeben muss) kommt auch kein Fehler. Die Therorie konnte ich aber im Netz nirgends verifizieren.

    Danke nochmal für eure Geduld. Ich habe das Gefühl ich stehe gerade mit beiden Füssen aufm Schlauch!!!

    EDIT:
    Ich hatte einen Fehler in der Reihenfolge der Anweisungen. "AS" kommt nach den Deklanationen. Er updatet zwar noch nicht 100%ig so wie ich will, aber ich stehe schonmal. Jetzt versuche ich zu laufen! :thumbsup:

    SQL-Abfrage

    1. CREATE PROCEDURE up_BenutzerTabelle11
    2. --@TEMPUSER_ID as int,
    3. --@MyDomainLogin varchar(30),
    4. @StartZeit datetime,
    5. @EndZeit datetime,
    6. ...
    7. as
    8. BEGIN
    9. SET NOCOUNT ON
    10. --SET @MyDomainlogin = SUSER_NAME()
    11. --SET @MyDomainLogin = SUBSTRING(@MyDomainLogin,CHARINDEX('\',@MyDomainLogin) + 1,30)
    12. UPDATE Tabelle1
    13. SET
    14. StartZeit = @StartZeit,
    15. EndZeit = @EndZeit,
    16. ...
    17. WHERE Mitarbeiter_ID = @Mitarbeiter_ID
    18. END
    19. GO

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ruediger_006“ ()

    ruediger_006 schrieb:

    Ich habe die Update-Anweisung vorher ja auf dem Server als Stored Procedure erstellt
    Du kannst die Routine direkt in Visual Studio debuggen - sogar im Einzelschrittmodus. Geh im Server-Explorer auf deine Datenverbindung, dann auf "Stored Procedures". Rechtsklick auf die Update-Prozedur und "Debug" wählen - daraufhin musst du die Parameter manuell angeben. Nach dem Klick auf OK springt er in den Code und du kannst wie gewohnt im Einzelschrittmodus durch deine Prozedur gehen. Außerdem siehst du den Inhalt der lokalen Variablen und Parameter. So kannst du schnell testen, ob der Fehler in der DB oder im Programm liegt. In der Datenansicht in VS siehst du dann, was dabei rausgekommen ist (einfach die Tabelle im Server-Explorer anschauen). Zumindest mit MySQL funktioniert das prima.

    ruediger_006 schrieb:

    Er updatet zwar noch nicht 100%ig so wie ich will
    Von hier aus wird es langsam schwierig mit der Hilfe - nicht etwa, weil du schon ziemlich weit bist, sondern weil ich deine Aktionen gerade nicht an nem Beispiel nachvollziehen kann (habe keinen *SQL-Server zur Hand, mit dem ich das nachbauen könnte). Zumindest scheint das Update ja generell schon zu funktionieren, nur eben nicht genau wie gewollt. Das ist doch schonmal gut.

    Ich lese so beiläufig, dass du einen BindingNavigator verwendest - nimm lieber das DataGridView - das dürfte angenehmer sein als sich durch die Datensätze zu klicken. Alles, was du darin änderst, wird auch an die DB übertragen (nachdem du es abgeschickt hast, wie das in deinem generieten Codestück schon steht).
    Gruß
    hal2000
    Hallo Hal!

    Es läuft alles! Das mit dem Debuggen ist natürlich gut zu wissen, wenn mal was ist.

    Ich habe den Updatecode oben noch dem lauffähigen angepasst, damit er als Grundlage für andere dienen kann.

    Ganz herzlichen Dank, du hast mir wirklich sehr geholfen!

    Schönen Tag wünsche ich noch!