Si vous souhaitez que les utilisateurs choisissent dans la vue, pourquoi accordez-vous à la table? Par «révoquer», voulez-vous dire explicitement révoquer / refuser? Le refus remplacera l'octroi, il y a donc votre problème ... vous devriez pouvoir accomplir cela en ajoutant l'octroi à la vue et en ne faisant rien de toute façon sur les tables.
Voici un exemple rapide où SELECT
n'a pas été explicitement accordé sur la table, mais l'a été dans la vue. L'utilisateur peut sélectionner dans la vue mais pas dans la table.
CREATE USER foo WITHOUT LOGIN;
GO
CREATE TABLE dbo.a(id INT);
CREATE TABLE dbo.b(id INT);
GO
CREATE VIEW dbo.v
AS
SELECT a.id FROM a INNER JOIN b ON a.id = b.id;
GO
GRANT SELECT ON dbo.v TO foo;
GO
EXECUTE AS USER = N'foo';
GO
-- works:
SELECT id FROM dbo.v;
GO
-- Msg 229, SELECT denied:
SELECT id FROM dbo.a;
GO
REVERT;
Notez que cela suppose foo
qu'aucun privilège élevé ne lui a été accordé via des autorisations explicites sur le schéma ou la base de données, ou via l'appartenance à un rôle ou à un groupe.
Étant donné que vous utilisez des tables dans plusieurs bases de données (désolé d'avoir manqué la fin de cette première phrase au départ), vous pouvez également avoir besoin d'autorisations explicites sur les tables de la base de données où la vue n'existe pas. Afin d'éviter d'accorder une sélection aux tables, vous pouvez créer une vue dans chaque base de données, puis joindre les vues.
Créez deux bases de données et un identifiant:
CREATE DATABASE d1;
GO
CREATE DATABASE d2;
GO
USE [master];
GO
CREATE LOGIN blat WITH PASSWORD = 'x', CHECK_POLICY = OFF;
GO
Dans la base de données d1
, créez un utilisateur, puis créez une table et une vue simple sur cette table. Accordez une sélection à l'utilisateur uniquement par rapport à la vue:
USE d1;
GO
CREATE USER blat FROM LOGIN blat;
GO
CREATE TABLE dbo.t1(id INT);
GO
CREATE VIEW dbo.v1
AS
SELECT id FROM dbo.t1;
GO
GRANT SELECT ON dbo.v1 TO blat;
GO
Maintenant, dans la deuxième base de données, créez l'utilisateur, puis créez une autre table et une vue qui joint cette table à la vue dans d1
. Accordez la sélection uniquement à la vue.
USE d2;
GO
CREATE USER blat FROM LOGIN blat;
GO
CREATE TABLE dbo.t2(id INT);
GO
CREATE VIEW dbo.v2
AS
SELECT v1.id FROM dbo.t2
INNER JOIN d1.dbo.v1 AS v1
ON t2.id = v1.id;
GO
GRANT SELECT ON dbo.v2 TO blat;
GO
Lancez maintenant une nouvelle fenêtre de requête et modifiez les informations d'identification pour la connexion blat
( EXECUTE AS
ne fonctionne pas ici). Exécutez ensuite ce qui suit à partir du contexte de l'une ou l'autre base de données, et cela devrait fonctionner correctement:
SELECT id FROM d1.dbo.v2;
Ceux-ci devraient tous deux générer des erreurs Msg 229:
SELECT id FROM d1.dbo.t1;
GO
SELECT id FROM d2.dbo.t2;
Résultats:
Msg 229, niveau 14, état 5, ligne 1
L'autorisation SELECT a été refusée sur l'objet 't1', la base de données 'd1', le schéma 'dbo'.
Msg 229, niveau 14, état 5, ligne 3
L'autorisation SELECT a été refusée sur l'objet 't2', la base de données 'd2', le schéma 'dbo'.