205 votes

Vérifier si un login SQL Server existe déjà

Je dois vérifier si un login spécifique existe déjà sur le serveur SQL, et s'il n'existe pas, je dois l'ajouter.

J'ai trouvé le code suivant pour ajouter le login à la base de données, mais je veux l'intégrer dans une instruction IF (d'une manière ou d'une autre) pour vérifier d'abord si le login existe.

CREATE LOGIN [myUsername] WITH PASSWORD=N'myPassword', 
DEFAULT_LANGUAGE=[us_english], 
CHECK_EXPIRATION=OFF, 
CHECK_POLICY=OFF 
GO

Je comprends que je dois interroger une base de données système, mais je ne sais pas par où commencer !

10 votes

Il s'agit d'une question importante, mais telle qu'elle est formulée, elle semble omettre une distinction importante : utilisateur vs. connexion. Le duplicata potentiel auquel Jon a fait référence semble vraiment concerner les utilisateurs. Cette question mentionne "utilisateur" dans le titre, mais traite des connexions dans le code de la question et dans la réponse acceptée. J'ai modifié le titre et la question en conséquence.

1 votes

Juste pour ajouter au commentaire de @LarsH, logins sont associés à une instance du serveur SQL, et utilisateurs sont associés à une base de données spécifique. Les utilisateurs de la base de données peuvent être créés à partir des connexions au serveur, de sorte qu'ils ont accès à une base de données spécifique. Voir cet excellent article et en fait toute la série dont il fait partie (Stariway to SQL Server Security)

320voto

Derek Morrison Points 2359

Voici une façon de le faire dans le serveur SQL 2005 et les versions ultérieures sans utiliser la vue syslogins dépréciée :

IF NOT EXISTS 
    (SELECT name  
     FROM master.sys.server_principals
     WHERE name = 'LoginName')
BEGIN
    CREATE LOGIN [LoginName] WITH PASSWORD = N'password'
END

La vue server_principals est utilisée à la place de sql_logins car cette dernière ne liste pas les identifiants Windows.

Si vous devez vérifier l'existence d'un utilisateur dans une base de données particulière avant de le créer, vous pouvez le faire :

USE your_db_name

IF NOT EXISTS
    (SELECT name
     FROM sys.database_principals
     WHERE name = 'Bob')
BEGIN
    CREATE USER [Bob] FOR LOGIN [Bob] 
END

17 votes

Meilleure réponse, aucun sql dynamique n'est impliqué, ni aucune utilisation de vue dépréciée. Merci !

9 votes

Dans le cas de SQL Azure, les deux tables cibles sont sys.sql_logins et sys.sysusers. Il serait bon de le préciser dans la réponse.

1 votes

Pas utile si votre script doit utiliser un nom d'utilisateur variable.

151voto

John Nolan Points 16633

De ici

If not Exists (select loginname from master.dbo.syslogins 
    where name = @loginName and dbname = 'PUBS')
Begin
    Select @SqlStatement = 'CREATE LOGIN ' + QUOTENAME(@loginName) + ' 
    FROM WINDOWS WITH DEFAULT_DATABASE=[PUBS], DEFAULT_LANGUAGE=[us_english]')

    EXEC sp_executesql @SqlStatement
End

8 votes

Vous devez utiliser QUOTENAME pour éviter l'injection sql. L'attaquant peut passer un @loginName comme x] with password ''y'';\r\ndrop table foo;\r\n

3 votes

Pourquoi était-il nécessaire de créer une instruction sous forme de chaîne de caractères, puis d'utiliser sp_executesql, plutôt que d'entrer directement dans le système ? CREATE LOGIN [@loginName] FROM ... ? Pardonnez mon ignorance, j'aimerais apprendre...

5 votes

@LarsH : La création de l'instruction sous forme de chaîne est nécessaire parce que CREATE LOGIN ne peut pas utiliser de paramètre pour le nom de connexion, il faut une chaîne littérale. Je ne sais pas pourquoi, mais j'ai découvert à la dure que c'est vrai.

32voto

Bomlin Points 370

Comme un ajout mineur à ce fil, en général vous voulez éviter d'utiliser les vues qui commencent par sys.sys* comme Microsoft les inclut seulement pour la compatibilité rétroactive. Pour votre code, vous devriez probablement utiliser sys.server_principals. Cela suppose que vous utilisez SQL 2005 ou une version plus récente.

0 votes

Testé, fonctionne, et plus actuel que les autres réponses. +1 à vous aussi.

0 votes

Oui, avec 2005, Microsoft a supprimé l'accès direct aux tables du système. Pour ne pas casser le vieux code, ils ont inclus des vues qui avaient le même nom que les anciennes tables. Cependant, elles ne sont destinées qu'à l'ancien code et le code plus récent doit utiliser les nouvelles vues. Dans BOL, faites une recherche sur Mapping System Tables pour savoir ce que vous devez utiliser.

8voto

Marc Points 574

Essayez ceci (remplacez "user" par le nom de connexion réel) :

IF NOT EXISTS(
SELECT name 
FROM [master].[sys].[syslogins]
WHERE NAME = 'user')

BEGIN 
    --create login here
END

0 votes

@Marc : Désolé mais vous avez tort. La table [syslogins] garde les logins et la table [sysusers] garde les utilisateurs.

6voto

David Stratton Points 45298

Cela fonctionne sur SQL Server 2000.

use master
select count(*) From sysxlogins WHERE NAME = 'myUsername'

sur SQL 2005, changez la 2ème ligne en

select count(*) From syslogins WHERE NAME = 'myUsername'

Je ne suis pas sûr de SQL 2008, mais je suppose que ce sera la même chose que SQL 2005 et si ce n'est pas le cas, cela devrait vous donner une idée d'où commencer à chercher.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X