次のようにログインを作成しようとしています。
CREATE LOGIN [Test] WITH PASSWORD='Test123', SID=SID_BINARY(N'S-1-5-21-408552231-458724953-3089381293-513')
しかし、SIDがどのように見えるかに関係なく、バイナリ入力のみを受け入れ、サブクエリなどは実際には受け入れません。
Incorrect syntax near 'SID'.
文字列を使用してSIDでログインを作成する方法はありますか?
SID_BINARY()
の面白いところ-この場合はbinary(28)
を出力しますが、_CREATE LOGIN
_はbinary(16)
を期待します。ソロモンが指摘し、曖昧さがないようにここに追加すると、これは投稿したWindows識別子に基づいて、またはそれにマップできるSQL Server SIDを作成する方法がないことを意味しますあなたの質問です。_CREATE LOGIN ... FROM Windows
_が必要です。
ただし、最初の問題は構文エラーです。これが発生する理由は、_CREATE LOGIN
_ステートメントで式を使用できず、変数も使用できないため、動的SQLを構築する必要があるためです。
次のように28バイトすべてを使用しようとしました。
_DECLARE @sid_in varchar(100);
SET @sid_in = 'S-1-5-21-408552231-458724953-3089381293-513';
DECLARE @sql nvarchar(max) = N'CREATE LOGIN [Test] WITH PASSWORD = N''foo'',
SID = ' + CONVERT(varchar(64), SID_BINARY(@sid_in), 1) + N';';
PRINT @sql;
_
収量:
_CREATE LOGIN [Test] WITH PASSWORD = N'foo',
SID = 0x01050000000000051500000027035A185996571BAD3724B801020000;
_
もちろん、予想どおり、そのSQLを実行するとエラーが発生しました。
メッセージ15419、レベル16、状態1
指定されたパラメーターsidは、binary(16)である必要があります。
だから私は16バイトに切り捨てることがうまくいくかどうか疑問に思いました。 12バイトの損失が問題になるはずなので、これは互換性がないと思いました:
_DECLARE @sid_in varchar(100), @sid_out varchar(100);
SET @sid_in = 'S-1-5-21-408552231-458724953-3089381293-513';
SELECT original = SID_BINARY(@sid_in);
SELECT trimmed = CONVERT(binary(16), SID_BINARY(@sid_in));
_
結果:
_original
----------------------------------------------------------
0x01050000000000051500000027035A185996571BAD3724B801020000
trimmed
0x01050000000000051500000027035A18
_
しかし、私はそれを試しました、そしてそれは(一種の)うまくいきました。次に例を示します。
_DECLARE @sid_in varchar(100);
SET @sid_in = 'S-1-5-21-408552231-458724953-3089381293-513';
DECLARE @sql nvarchar(max) = N'CREATE LOGIN [Test] WITH PASSWORD = N''foo'',
SID = ' + CONVERT(varchar(64), CONVERT(binary(16),SID_BINARY(@sid_in)), 1) + N';';
EXEC sys.sp_executesql @sql;
_
そして、これらの12バイトをトリミングしてもほとんど効果がないことを証明するには、次のようにします。
_DECLARE @sid_in varchar(100);
SET @sid_in = 'S-1-5-21-408552231-458724953-3089381293-513';
SELECT SUSER_SNAME(CONVERT(binary(16),SID_BINARY(@sid_in)));
_
結果:
_----
Test
_
これは、Windows S-1 ...識別子が与えられた場合でも正しいログインに到達できるようにコードを記述できることを意味します。ただし、このトリミングには副作用がある場合とない場合があります。一部のデータがなくなっているため、渡した元のSIDに戻すことはできません。したがって、作成した場合 関数@eckesは上記を指します の場合、予想とは少し異なる出力が見つかります。
_SELECT name, sid, ws1 = dbo.fn_SIDToString(sid)
FROM sys.server_principals
WHERE name = N'Test';
_
結果:
_name sid ws1
---- ---------------------------------- ------------------
Test 0x01050000000000051500000027035A18 S-1-5-21-408552231
_
それは許容される場合と許容されない場合があります。 Windows識別子について、またはSQL認証ユーザーを作成する理由を正確には知りません。 です 一見すると、これがあなたのニーズを満たすかどうかを知るために1つにマッピングされるように見えます。しかし、それは構文エラーと28/16問題の両方を通過します。
私が使用した機能、リンクが切れた場合に備えてここに含まれています:
_CREATE FUNCTION [dbo].[fn_SIDToString]
(
@BinSID AS VARBINARY(100)
)
RETURNS VARCHAR(100)
AS BEGIN
IF LEN(@BinSID) % 4 <> 0 RETURN(NULL)
DECLARE @StringSID VARCHAR(100)
DECLARE @i AS INT
DECLARE @j AS INT
SELECT @StringSID = 'S-'
+ CONVERT(VARCHAR, CONVERT(INT, CONVERT(VARBINARY, SUBSTRING(@BinSID, 1, 1))))
SELECT @StringSID = @StringSID + '-'
+ CONVERT(VARCHAR, CONVERT(INT, CONVERT(VARBINARY, SUBSTRING(@BinSID, 3, 6))))
SET @j = 9
SET @i = LEN(@BinSID)
WHILE @j < @i
BEGIN
DECLARE @val BINARY(4)
SELECT @val = SUBSTRING(@BinSID, @j, 4)
SELECT @StringSID = @StringSID + '-'
+ CONVERT(VARCHAR, CONVERT(BIGINT, CONVERT(VARBINARY, REVERSE(CONVERT(VARBINARY, @val)))))
SET @j = @j + 4
END
RETURN ( @StringSID )
END
_
ドキュメントには CREATE LOGIN
がSID値をバイナリデータ型として受け入れると記載されています(私の強調):
SID = sid
ログインを再作成するために使用されます。 SQL Server認証ログインのみに適用され、Windows認証ログインには適用されません。新しいSQL Server認証ログインのSIDを指定します。このオプションを使用しない場合、SQL Serverは自動的にSIDを割り当てます。 SID構造は、SQL Serverのバージョンによって異なります。 SQL ServerログインSID:GUIDに基づく16バイト(binary(16))リテラル値たとえば、SID = 0x14585E90117152449347750164BA00A7。
そして
DROP LOGIN TestLogin; GO CREATE LOGIN TestLogin WITH PASSWORD = 'SuperSecret52&&', SID = 0x241C11948AEEB749B0D22646DB1A19F2; SELECT * FROM sys.sql_logins WHERE name = 'TestLogin'; GO
SQLログインを使用している場合、バイナリSID値を抽出して既存のログインのCREATE LOGIN
ステートメントを生成する一般的な方法の例として、 sp_help_revlogin を使用できます。 SQLログインでWindowsアカウントを操作するのはかなり難しいようです。
答えは簡単です。これを行うことはできません。
SQL Serverログイン(つまり、WITH PASSWORD='Test123', SID=...
ではなくFROM ...
)を作成しようとしていますが、Windows SID(つまり、0x01050000000000051500000027035A185996571BAD3724B801020000
の線に沿ったものではなく0x4D50DEDF91DABA4595F121BBA9E8D4AF
)を使用しています。 LowlyDBAの回答 で引用されているドキュメントには、次のように記載されています。
SQL Server認証ログインのみに適用され、Windows認証ログインには適用されません。
また、SQL Serverログインから使用しようとしているSIDを取得していません。これを機能させる方法はありません。アーロンのアプローチが動作するように見える唯一の理由(私は彼が使用しているSIDにonlyを参照しています;動的SQLのもの完全に正しいです)は、残りのバイトが16バイトだけになるように、余分なバイトを切り落とすことです。しかし、これを行うと、結果の値0x01050000000000051500000027035A18
が、0x0102030405060708090A0B0C0D0E0F10
のような独自の値を思いつくのと同じくらい恣意的になります。 SQL ServerログインSIDは、任意の識別子です。例えば:
CREATE LOGIN [Whozitz] WITH PASSWORD='Test123', SID=0x0102030405060708090A0B0C0D0E0F10;
SELECT SUSER_SNAME(0x0102030405060708090A0B0C0D0E0F10);
-- Whozitz
それでも、意味のある識別子であるS-1-5-21-408552231-458724953-3089381293-513
から始めました。OS(または別のシステムから取得された可能性があるため、OSのどこかにある特定のエンティティ)を参照するだけでなく、文字列内のダッシュで区切られた/ SIDのSDDL形式は意味があります。 「1」はバージョン番号であり、決して変更されません。 「5」はエンティティのタイプを指していると思います。そして、残りのセグメントはタイプに基づいています。
ただし、SIDがSQL ServerとOSの間で完全に一致した場合でも、サーバープリンシパル/ログインがSQL Serverログインであるという事実は、実際の接続がないことを意味しますSQL Server内のSIDおよびOSレベルのSID。
他のシステムに存在するログインのSIDに基づいてSQL Serverログインを作成して、データベースを移動し、事後にログインを同期する必要がないようにする場合などは、以下の方法でのみ実行できます。 Windowsログインではなく、既存SQL Serverログイン。