2009-09-04 12 views
137

Necesito comprobar si ya existe un inicio de sesión específico en el servidor SQL, y si no es así, entonces tengo que agregarlo.Comprobando si ya existe un inicio de sesión de SQL Server

He encontrado el siguiente código para agregar realmente el inicio de sesión a la base de datos, pero quiero ajustar esto en una declaración IF (de alguna manera) para verificar si el inicio de sesión existe primero.

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

Entiendo que tengo que interrogar a una base de datos del sistema, ¡pero no estoy seguro por dónde empezar!

+0

la versión de SQL Server? – pjp

+10

Esta es una pregunta importante, pero tal como está redactada, parece pasar por alto una distinción importante: usuario vs. inicio de sesión. El posible duplicado al que Jon se vinculó parece ser realmente sobre los usuarios. Esta pregunta dice "usuario" en el título, pero trata de los inicios de sesión en el código de pregunta y en la respuesta aceptada. Edité el título y la pregunta en consecuencia. – LarsH

+1

Solo para agregar al comentario de @LarsH, ** inicios de sesión ** están asociados con una instancia de servidor SQL, y ** usuarios ** están asociados con una base de datos específica. Los usuarios de bases de datos se pueden crear a partir de los inicios de sesión del servidor, por lo que tienen acceso a una base de datos específica. Ver [este excelente artículo] (http://www.sqlservercentral.com/articles/Stairway+Series/109975/) y, de hecho, toda la serie de la que forma parte (Stariway to SQL Server Security) – DaveBoltman

Respuesta

116

De here

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 
+2

+1. Mejor respuesta que la mía. Buena respuesta. – David

+6

debe usar QUOTENAME para evitar la inyección sql. El atacante puede pasar un @loginName como 'x] con la contraseña '' y ''; \ r \ ndrop table foo; \ r \ n' –

+0

¡Buenas cosas, gracias chicos! –

5

Esto funciona en SQL Server 2000.

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

en SQL 2005, cambie la segunda línea de

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

No estoy seguro acerca de SQL 2008, pero supongo que será el mismo que SQL 2005 y si no, esto debería darte una idea de wh antes de comenzar a mirar.

8

Prueba esto (reemplace 'usuario' con el nombre de inicio de sesión real):

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

BEGIN 
    --create login here 
END 
+0

@Marc: lo siento pero estás equivocado. La tabla [syslogins] mantiene los inicios de sesión y la tabla [sysusers] mantiene a los usuarios. – abatishchev

27

Como una pequeña adición a este tema, en general se desea evitar el uso de las vistas que comienzan con sys.sys * tan Microsoft solo los está incluyendo por compatibilidad con versiones anteriores. Para su código, probablemente debería usar sys.server_principals. Esto supone que estás usando SQL 2005 o superior.

+0

Probado, funciona y más actual que las otras respuestas. +1 a usted también. – David

+0

bueno saber, gracias! – Marc

+0

Sí, con 2005, Microsoft quitó el acceso directo a las tablas del sistema. Para no romper el código antiguo, incluyen vistas que tenían el mismo nombre que las tablas antiguas.Sin embargo, solo están diseñados para código antiguo y el código más nuevo debe usar las vistas nuevas. En BOL, haga una búsqueda en Mapping System Tables para averiguar qué debe usar. – Bomlin

246

Aquí está una manera de hacer esto en SQL Server 2005 y versiones posteriores sin necesidad de utilizar las syslogins en desuso ver:

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

La vista server_principals se utiliza en lugar de sql_logins ya que este último no muestra los inicios de sesión de Windows.

Si necesita comprobar la existencia de un usuario en una base de datos en particular antes de la creación de ellos, entonces usted puede hacer esto:

USE your_db_name 

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

¡Agradable, gracias! –

+15

La mejor respuesta, no incluye sql dinámico ni uso de vista obsoleto. ¡Gracias! –

+4

En el caso de SQL Azure, las dos tablas de destino son sys.sql_logins y sys.sysusers; podría ser útil incluir esto en la respuesta. – Brett

4

¿qué exactamente quiere comprobar si hay entrada o usuario? se crea un inicio de sesión a nivel de servidor y se crea un usuario a nivel de base de datos para que el inicio de sesión sea único en el servidor

También un usuario se crea en un inicio de sesión, un usuario sin inicio de sesión es un usuario huérfano no puede llevar a cabo de inicio de sesión de SQL Server sin un inicio de sesión

quizá u necesidad de esta comprobación

de inicio de sesión

select 'X' from master.dbo.syslogins where loginname=<username> 

la consulta anterior de retorno 'X' si existe otra entrada devuelto nulo

continuación, crear un inicio de sesión

CREATE LOGIN <username> with PASSWORD=<password> 

esto crea un inicio de sesión en el servidor SQL.pero sólo acepta contraseñas fuertes

crear un usuario en cada base de datos que desea para iniciar la sesión como

CREATE USER <username> for login <username> 

de asignación de derechos de ejecución al usuario

GRANT EXECUTE TO <username> 

debe tener permisos de administrador de sistemas o decir 'sa 'para abreviar

puede escribir un procedimiento sql para eso en una base de datos

create proc createuser 
(
@username varchar(50), 
@password varchar(50) 
) 
as 
begin 
if not exists(select 'X' from master.dbo.syslogins where [email protected]) 
begin 
if not exists(select 'X' from sysusers where [email protected]) 
begin 
exec('CREATE LOGIN '[email protected]+' WITH PASSWORD='''[email protected]+'''') 
exec('CREATE USER '[email protected]+' FOR LOGIN '[email protected]) 
exec('GRANT EXECUTE TO '[email protected]) 
end 
end 
end 
0

Primero se tiene que comprobar la existencia de inicio de sesión utilizando syslogins ver:

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

entonces usted tiene que comprobar su existencia base de datos:

USE your_dbname 

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

No sé - diciendo que "tienes que verificar la existencia de inicio de sesión usando la vista syslogins", y luego publicar el código que no usa esa vista parece un problema de copiar y pegar. Además, después de la primera afirmación, la línea "Entonces debe verificar la existencia de su base de datos", al usar una forma paralela, parece que le está pidiendo a alguien que verifique la existencia de una base de datos, no un usuario de nivel DB. Y debe especificar que el segundo lote debe ejecutarse dentro del DB de destino. En general, esta es solo una explicación muy pobre. Y ya que lo agregó cinco años después de la respuesta más alta, dijo lo mismo, pero mejor ... –

1

Puede utilizar la función incorporada:

SUSER_ID ([ 'myUsername' ]) 

a través de

IF [value] IS NULL [statement] 

como:

IF SUSER_ID (N'myUsername') IS NULL 
CREATE LOGIN [myUsername] WITH PASSWORD=N'myPassword', 
DEFAULT_LANGUAGE=[us_english], 
CHECK_EXPIRATION=OFF, 
CHECK_POLICY=OFF 
GO 

https://technet.microsoft.com/en-us/library/ms176042(v=sql.110).aspx

Cuestiones relacionadas