SQL Server 로그인이 이미 있는지 확인


176

특정 로그인이 SQL Server에 이미 존재하는지 확인해야하며, 그렇지 않은 경우 추가해야합니다.

실제로 로그인을 데이터베이스에 추가하는 다음 코드를 찾았지만 이것을 IF 문으로 감싸서 로그인이 먼저 있는지 확인하고 싶습니다.

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

시스템 데이터베이스를 조사해야하지만 어디에서 시작할지 잘 모르겠습니다.


10
이것은 중요한 질문이지만, 문구와 같이 중요한 것은 사용자 대 로그인입니다. Jon이 연결 한 잠재적 중복은 실제로 사용자에 관한 것으로 보입니다. 이 질문은 제목에 "user"라고 말하지만 질문 코드와 허용되는 답변의 로그인을 처리합니다. 제목과 질문을 적절히 편집했습니다.
LarsH

1
@LarsH의 주석에 추가하기 위해 로그인 은 SQL Server 인스턴스와 연결 되고 사용자 는 특정 데이터베이스와 연결됩니다. 데이터베이스 사용자는 서버 로그인에서 작성할 수 있으므로 특정 데이터베이스에 액세스 할 수 있습니다. 참조 이 우수한 기사를 실제로 전체 시리즈는 (SQL 서버 보안에 Stariway)의 일부입니다
반전 엔지니어

답변:


141

에서 여기

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

6
SQL 주입을 방지하려면 QUOTENAME을 사용해야합니다. 공격자는 같은 @LoginName를 전달할 수 있습니다x] with password ''y'';\r\ndrop table foo;\r\n
레무스 Rusanu

2
명령문을 문자열로 만든 다음 직접 입력하지 않고 sp_executesql을 사용해야하는 이유는 무엇 CREATE LOGIN [@loginName] FROM ...입니까? 내 무지를 용서하고, 배우고 싶습니다 ...
LarsH

4
@LarsH : CREATE LOGIN은 로그인 이름에 매개 변수를 사용할 수 없으므로 문자열 리터럴이 필요하므로 명령문을 문자열로 작성해야합니다. 왜 그런지 잘 모르겠지만, 그것이 어려운 방법을 찾았습니다.
Joseph Bongaarts

@JosephBongaarts : 감사합니다. SELECT 문의 테이블 이름과 같습니다. 어쩌면 아이디어는 공격에 취약한 표면적을 줄이는 것이지만, 그것이 도움이 될지는 모르겠습니다.
LarsH

1
나는 전체적인 진술이 아니라 QUOTENAME()주위를 돌아 다니면서 @loginName수동 [및] 구분 기호를 제거 할 수 있다고 생각 합니다 @loginName.
brianary

288

더 이상 사용되지 않는 syslogins보기를 사용하지 않고 SQL Server 2005 이상에서이를 수행하는 방법은 다음과 같습니다.

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

server_principals보기는 sql_logins 대신 사용되며 후자는 Windows 로그인을 나열하지 않기 때문입니다.

사용자를 작성하기 전에 특정 데이터베이스에 사용자가 있는지 확인해야하는 경우 다음을 수행 할 수 있습니다.

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
최상의 답변, 동적 SQL 관련, 더 이상 사용되지 않는 뷰 사용. 감사!
캐스퍼 레온 닐슨

7
SQL Azure의 경우 두 개의 대상 테이블은 sys.sql_logins 및 sys.sysusers입니다.이를 답변에 포함시키는 것이 좋습니다.
Brett

스크립트가 변수 사용자 이름을 사용해야하는 경우에는 유용하지 않습니다.
Ross Presser

@Derek Morrison SID에 대한 조건을 하나 더 추가 할 수 있습니까
AstroBoy

30

이 스레드에 사소한 추가 사항으로, 일반적으로 Microsoft는 이전 버전과의 호환성을 위해 sys.sys *로 시작하는보기를 사용하지 않기를 원합니다. 코드에는 아마도 sys.server_principals를 사용해야합니다. 이것은 SQL 2005 이상을 사용한다고 가정합니다.


다른 답변보다 테스트되고 작동하며 최신 상태입니다. 당신에게도 +1합니다.
David

예, 2005 년에 Microsoft는 시스템 테이블에 직접 액세스했습니다. 이전 코드를 손상시키지 않기 위해 이전 테이블과 이름이 같은 뷰가 포함됩니다. 그러나 그것들은 오래된 코드만을위한 것이며 새로운 코드는 새로운 뷰를 사용해야합니다. BOL에서 맵핑 시스템 테이블을 검색하여 사용해야하는 내용을 찾으십시오.
Bomlin

11

내장 기능을 사용할 수 있습니다 :

SUSER_ID ( [ 'myUsername' ] )

통하다

IF [value] IS NULL [statement]

처럼:

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


정책 및 만료 검사를 비활성화하는 선택적 필드를 포함하도록 상향 조정되었습니다.
Archibald

8

이것을 시도하십시오 (실제 로그인 이름으로 'user'를 대체하십시오).

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

BEGIN 
    --create login here
END

@ 마크 : 미안하지만 틀렸어. 테이블 [syslogins]은 로그인을 유지하고 테이블 [sysusers]는 사용자를 유지합니다.
abatishchev

6

이것은 SQL Server 2000에서 작동합니다.

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

SQL 2005에서 두 번째 줄을

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

SQL 2008에 대해 잘 모르겠지만 SQL 2005와 동일 할 것으로 예상되며 그렇지 않은 경우 어디에서 시작하는지에 대한 아이디어를 제공해야합니다.


5

정확히 로그인 또는 사용자 확인을 원하십니까? 서버 레벨에서 로그인이 작성되고 데이터베이스 레벨에서 사용자가 작성되므로 서버에서 로그인이 고유합니다.

또한 사용자가 로그인에 대해 생성되고 로그인이없는 사용자는 고아 사용자이며 로그인하지 않고 SQL Server 로그인을 수행 할 수 없으므로 유용하지 않습니다

어쩌면 당신은 이것을 필요로합니다

로그인 확인

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

위의 쿼리는 로그인이 존재하면 'X'를 반환하고 그렇지 않으면 null을 반환

그런 다음 로그인을 만듭니다

CREATE LOGIN <username> with PASSWORD=<password>

이것은 SQL Server에 로그인을 생성하지만 강력한 암호 만 허용합니다.

로그인하려는 각 데이터베이스에 사용자를 작성하십시오.

CREATE USER <username> for login <username>

사용자에게 실행 권한을 할당

 GRANT EXECUTE TO <username>

SYSADMIN 권한이 있거나 짧게 'sa'라고 말해야합니다.

당신은 데이터베이스에 대한 SQL 절차를 작성할 수 있습니다

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

5

로그인, 역할, 사용자 등의 이름 충돌 type을 처리하려면 Microsoft sys.database_principals 설명서 에 따라 열을 확인해야 합니다

사용자 이름 등, 사용 특별한 chacters 처리하기 위해, N'<name>'그리고 [<name>]그에 따라합니다.

로그인 생성

USE MASTER
IF NOT EXISTS (SELECT 1 FROM master.sys.server_principals WHERE 
[name] = N'<loginname>' and [type] IN ('C','E', 'G', 'K', 'S', 'U'))
    CREATE LOGIN [<loginname>] <further parameters>

데이터베이스 사용자 생성

USE <databasename>
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE 
[name] = N'<username>' and [type] IN ('C','E', 'G', 'K', 'S', 'U'))
    CREATE USER [<username>] FOR LOGIN [<loginname>]

데이터베이스 역할 생성

USE <databasename>
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE 
[name] = N'<rolename>' and Type = 'R')
    CREATE ROLE [<rolename>]

역할에 사용자 추가

USE <databasename>
EXEC sp_addrolemember N'<rolename>', N'<username>'

역할에 대한 권한 부여

USE <databasename>
GRANT SELECT ON [<tablename>] TO [<rolename>]
GRANT UPDATE ON [<tablename>] ([<columnname>]) TO [<rolename>]
GRANT EXECUTE ON [<procedurename>] TO [<rolename>]


-1

먼저 syslogins보기를 사용하여 로그인 존재를 확인해야합니다.

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

그런 다음 데이터베이스 존재를 확인해야합니다.

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

1
나는 "syslogins보기를 사용하여 로그인 존재를 확인해야합니다"라고 말한 다음 해당보기를 사용하지 않는 코드를 게시하면 복사 및 붙여 넣기 문제처럼 보입니다. 또한 첫 번째 명령문 다음에 병렬 양식을 사용하여 "데이터베이스 존재를 확인해야합니다"행은 DB 레벨 사용자가 아닌 데이터베이스의 존재를 누군가에게 확인하도록 요청하는 것처럼 보입니다. 그리고 두 번째 배치가 대상 DB 내에서 실행되도록 지정해야합니다. 전반적으로 이것은 매우 나쁜 설명입니다. 그리고 당신이 최고 지지율이 높은 답변을 낸 지 5 년 후에 그것을 추가 한 이후로, 더 낫습니다…
Laughing Vergil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.