Sélectionnez l'autorisation dans la procédure stockée?

8

J'ai accordé à un utilisateur la permission d'exécuter une procédure stockée qui utilise du SQL dynamique. Mais quand il essaie de l'exécuter, il obtient l'erreur:

L'autorisation SELECT a été refusée sur l'objet '[nom de la table]', la base de données '[nom de la base de données]', le schéma 'dbo'.

L'utilisateur doit-il être autorisé à accéder aux tables utilisées par la procédure stockée? Cela n'aurait pas vraiment de sens pour moi.

xdumaine
la source

Réponses:

5

Ok, sur la base du commentaire ci-dessus et selon mes soupçons - il semble que vous essayiez d'exécuter du SQL dynamique dans votre procédure stockée.

Ce dont vous devez vous souvenir, c'est que lorsque vous effectuez cette opération, elle n'est pas exécutée dans le contexte de la procédure stockée - elle est exécutée dans une nouvelle session. Pour cette raison, le fait que l'instruction est appelée dans une procédure stockée est un point discutable et vous devrez accorder une autorisation explicite sur les objets que votre SQL dynamique utilise.

Si vous ne voulez pas faire cela, je remanierais votre procédure stockée pour ne pas utiliser le SQL dynamique.

Le lien ci-dessous de Microsoft devrait vous aider avec votre problème:

Problème: contexte de sécurité des instructions SQL dynamiques dans une procédure stockée (archive Wayback Machine)

Ce problème se produit car une requête d'exécution dynamique (sp_executesql ou EXECUTE) s'exécute dans un contexte distinct de la procédure stockée principale; il s'exécute dans le contexte de sécurité de l'utilisateur qui exécute la procédure stockée et non dans le contexte de sécurité du propriétaire de la procédure stockée.

Ceci est également abordé dans l'article (plus récent) de Microsoft Docs:

Écriture de Secure Dynamic SQL dans SQL Server

L'exécution d'instructions SQL créées dynamiquement dans votre code de procédure rompt la chaîne de propriété, ce qui oblige SQL Server à vérifier les autorisations de l'appelant par rapport aux objets auxquels SQL dynamique accède.

DBA mondial
la source
2

Il semble qu'il existe différents propriétaires de la procédure ainsi que l'objet sous-jacent que le SELECT interroge. Tout cela a à voir avec les chaînes de propriété . Voir l'exemple ci-dessous pour une brève explication et une démonstration de ce dont je parle:

use YourTestDatabase;
go

create login TestLogin1
with 
    password = 'password',
    check_policy = off;
go

create user TestUser1
for login TestLogin1;
go

create table Table1
(
    id int identity(1, 1) not null,
    SomeString varchar(30) not null
        default replicate('a', 30)
);
go

insert into Table1
values(default);
go 10

create proc Proc1
as
    select *
    from Table1;
go


grant execute
on Proc1
to TestUser1;
go

-- this works because permissions aren't checked
--  on Table1.  That is why TestUser1 can get the
--  result set without SELECT permissions on Table1
execute as user = 'TestUser1';
go

exec Proc1;
go

revert;
go

-- let's change the owner of Proc1 so that the 
--  ownership chain is broken and permissions are
--  checked on Table1
alter authorization
on Proc1
to TestUser1;
go

-- this no longer works because permissions are now
--  checked on Table1, which TestUser1 does not have
--  SELECT permissions on
execute as user = 'TestUser1';
go

exec Proc1;
go

revert;
go

Si vous souhaitez connaître la propriété de vos objets, vous pouvez exécuter la requête ci-dessous (évidemment en modifiant la clause WHERE pour inclure vos noms d'objets spécifiques):

select
    o.name,
    o.type_desc,
    case
        when o.principal_id is null
            then sp.name
        else dp.name
    end as principal_name
from sys.objects o
inner join sys.schemas s
on o.schema_id = s.schema_id
left join sys.database_principals dp
on o.principal_id = dp.principal_id
left join sys.database_principals sp
on s.principal_id = sp.principal_id
where o.name in
(
    'Table1',
    'Proc1'
);
Thomas Stringer
la source