Es geht um das Rechteverhältnis von Stored Procedures zu
Views. In meiner SP wird anhand von Übergabeparameter in
einer Caseverschachtelung ermittel auf welche View die SP
zugreifen soll.
Der User, der dies tut, hat aber nur auf einzelne dieser
Views "Select" Berechtigung. Es ist gewollt, dass im
entsprechenden Fall eine Zugriffsverweigerung hochkommt
und ansonsten die regulären Daten der erlaubten view.
Schicke ich die Select Statements unter dem entsprechenden
Useraccount direkt vom QueryAnalyser ab, habe ich den
gewünschten Effekt.
Offensichtlich ist es also so, dass es ausreicht, wenn ein
User die Berechtigung auf eine SP hat. Die SP liefert ihm
alle Daten, auch wenn die der SP zugrundeliegenden Views
den Zugriff sogar explizit für diesen User "SELECT"
verweigern.
Offensichtlich läuft der SELECT innerhalb der SP nicht
mehr im Account des eigentlichen Users sondern in einem
anderen (systemaccount?).
Wie kann ich dieses Problem jetzt umgehen? Ich muss den
User auf die SP berechtigen. Innerhalb der SP muss sich
aber dann entscheiden, ob der User die gewünschten Daten
sehen darf oder nicht.
Ich danke im voraus schonmal allen, die sich meinem
Problemche annehmen...
Viele Grüsse
Andreas Haberer
Andreas Haberer <andreas...@advantage-it.de> schrieb ...
> Es geht um das Rechteverhältnis von Stored Procedures zu
> Views. In meiner SP wird anhand von Übergabeparameter in
> einer Caseverschachtelung ermittel auf welche View die SP
> zugreifen soll.
> Der User, der dies tut, hat aber nur auf einzelne dieser
> Views "Select" Berechtigung. Es ist gewollt, dass im
> entsprechenden Fall eine Zugriffsverweigerung hochkommt
> und ansonsten die regulären Daten der erlaubten view.
> Offensichtlich läuft der SELECT innerhalb der SP nicht
> mehr im Account des eigentlichen Users sondern in einem
> anderen (systemaccount?).
Solange die Besitzkette der Objekte nicht unterbrochen
ist, prüft der SQL Server nicht mehr die Einzelobjekte.
Siehe dazu auch "Besitzketten" in der Online Dokumentation.
Und in den meisten Fällen ist das der "dbo".
Um eine Überprüfung mit den Rechten des angemeldeten
Benutzers zu erzwingen, wäre in Deinem Falle das
die jeweiligen SQL Anweisung mittels EXEC(...)
zu explizit auszuführen. Dann wird eine Überprüfung
mit dem aktuellen Benutzer vorgenommen.
Nachteilig ist dabei, dass Du einen Vorteil der Prozeduren,
nämlich den vorkompilierten Plan, verlierst. Deswegen ist es
evtl. optimaler, wenn auch aufwändiger, via IS_MEMBER() etc.
die Zugehörigkeit der Benutzer
zu bestimmten Rollen zu prüfen.
Gruss
Elmar
Dabei handelt es sich um sogenannte Ownership Chains. Wenn alle Objekte auf
die die Stored Procedure zugreift den selben Owner haben (und das sollte
auch so sein!) dann werden nur am obersten Objekt die Rechte gecheckt. In
deinem Fall in der Stored Procedure. Da der User Rechte auf die Stored
Procedure hat, bekommt er auch implizit die Rechte auf den darunter
liegenden Objekten.
Dadurch kann er über die Stored Procedure auf die darunter liegenden Objekte
zugreifen, allerdings nicht direkt auf die Objekte wenn er dort nicht auch
die Berechtigungen hat.
Das ist ein gewolltes Verhalten, um den Usern zb. nur die Berechtigungen zu
geben über die SP oder Views auf die Tabellen zuzugreifen, aber nicht direkt
auf die Tabellen. Genauere Infos dazu findest du in den BOL.
mfG Herbert Albert
"Andreas Haberer" <andreas...@advantage-it.de> schrieb im Newsbeitrag
news:03e201c2df3c$8a8b4510$3001...@phx.gbl...
Ich bin jetzt den Weg mit EXECUTE gegangen. Das
funktioniert....auch unter der Premisse dass der
Ausführungsplan nun nicht mehr vorkompiliert ist.
Auf die zweite Variante, über "is_member", kam ich heute
morgen auch schon alleine. Da stosse ich aber auf ein
neues Problem: Ich arbeite mit lokalen NT Benutzergruppen
auf dem Datenbankserver, auf die Domäinuser berechtigt
werden. Diese NT Benutzergruppen hole ich mir in den SQL
Server als User und berechtige sie auf die SP's...soweit
nix dramatisches.
Mache ich jetzt aber einen Select auf die
Systemfunktion "user", oder "Session_user" dann erhalte
ich nicht den Namen der NT Benutzergruppe zu der er
gehört, sondern seinen direkten Domänennamen (NetzID)...
Solltest Du mir auch in diesem Fall helfen können, wäre
das natürlich noch ein alternativer Weg den ich gehen
würde.
Also erst mal vielen Dank Herbert und vielen Dank Elmar
für Eure Hilfe.
Viele Grüsse
Andreas
>-----Originalnachricht-----
>.
>
Andreas Haberer <andreas...@advantage-it.de> schrieb ...
> Auf die zweite Variante, über "is_member", kam ich heute
> morgen auch schon alleine. Da stosse ich aber auf ein
> neues Problem: Ich arbeite mit lokalen NT Benutzergruppen
> auf dem Datenbankserver, auf die Domäinuser berechtigt
> werden. Diese NT Benutzergruppen hole ich mir in den SQL
> Server als User und berechtige sie auf die SP's...soweit
> nix dramatisches.
> Mache ich jetzt aber einen Select auf die
> Systemfunktion "user", oder "Session_user" dann erhalte
> ich nicht den Namen der NT Benutzergruppe zu der er
> gehört, sondern seinen direkten Domänennamen (NetzID)...
Auch wenn Du mit Gruppen-Berechtigungen arbeitest (sei es
lokale oder Domänenbenutzergruppen) wird der angemeldete
Benutzer immer über sein Konto identifiziert.
Jetzt wieder auf die Gruppen-Mitgliedschaft rückschliessen,
würde ich für den Zweck allerdings nicht (was auch ziemlich
kompliziert werden kann, wenns verschachtelte Gruppen etc.
gibt).
Ein durchgängigeres Konzept wäre, hier mit SQL Server
Rollen zu arbeiten, und denen jeweils die NT-Gruppen
unterzuordnen. Das gibt IMO eine bessere Flexibilität
bei Änderungen (neue, andere Gruppen, Domänen etc.)
Und vermeidet, dass man die SQL Server Berechtigungen
häufiger ändern muss, weil sich Benutzergruppen ändern.
Für den Test reicht dann ein
IS_MEMBER('VerkaufsRolle') = 1
aus - wobei IS_MEMBER auch für NT-Gruppen funktioniert.
Beachte dabei, das die "sysadmin" Gruppe und "dbo" sowie
eigenbaute Gruppe je nach Anwendungsfall teilweise
gesondert behandelt werden müssen, z. B.
IS_SRVROLEMEMBER('sysadmin') = 1
Eine Überprüfung könnte in etwa aussehen:
-- Zugriff erlaubt?
IF NOT (IS_SRVROLEMEMBER( 'sysadmin') AND
NOT (IS_MEMBER( 'db_owner' ) = 1) AND
NOT (IS_MEMBER( 'BenutzerRolle' ) = 1)
BEGIN
RAISERROR( 15247, -1, -1 )
RETURN -4
END
SELECT ...
Gruss
Elmar