6

Alter LOGIN を使用して、既存の SQL ログインのパスワードを更新しようとしています。

以下の作品を知っている

ALTER LOGIN [username1] WITH PASSWORD = 'somenewpassword123';

ただし、ローカル変数を使用しようとすると

DECLARE @newpass nvarchar(max);
SET @newpass = 'P@ssw0rd12345';
ALTER LOGIN [username1] WITH PASSWORD = @newpass;

これは失敗します。変数に [] 中かっこを追加すると、SSMS クエリ エディター内でこれが解決されるようですが、C# でクエリを書き出すことによってプログラムでこれを使用すると、上記のステートメントと同じエラー (PASSWORD の構文エラー) で失敗します。

C# アプリ内のコード

public static int UpdateSqlLoginPassword(DbContext context, string loginName, string password)
{
 try
 {
  string updatePassword =
         @"  SET NOCOUNT ON
          DECLARE @loginName AS nvarchar(max) = {0}
          DECLARE @password AS nvarchar(max) = {1}
          EXEC('
          USE master
          ALTER LOGIN ['+ @loginName + '] WITH PASSWORD = ['+ @password + ']
          ')";
  return context.Database.ExecuteSqlCommand(updatePassword, loginName, password);
 }
 catch (Exception)
 {  
  return -2;
 }
}

また、パスワードをハッシュしようとしましたが (変数の問題であると考えています)、ここでの構文は受け入れられません。

DECLARE @newpass nvarchar(max);
SET @newpass = 'P@ssw0rd12345';
DECLARE @hashedpass varbinary(max);
SET @hashedpass = HASHBYTES('SHA1', CONVERT(nvarchar(max),@newpass));

ALTER LOGIN [newuser10] WITH PASSWORD = @hashedpass HASHED;
SELECT @hashedpass;

固定値の代わりに変数を使用してSQLでログインのパスワードを更新する方法を理解するのを手伝ってくれる人はいますか?

前もって感謝します

アップデート

チャーリーからの提案に基づいて、次のことも試しました

public static int UpdateSqlLoginPassword(DbContext context, string loginName, string password)
        {
            try
            {
                string updatePassword =
                    @"ALTER LOGIN [' + @loginName +'] WITH PASSWORD =  @password ";
                return context.Database.ExecuteSqlCommand(updatePassword, new SqlParameter("loginName", loginName), new SqlParameter("password", password));
            }
            catch (Exception)
            {  
               return -2;
            }
        }

これでも sqlException Incorrect Syntax new '@password' が生成されます。パラメータをブレースすると

public static int UpdateSqlLoginPassword(DbContext context, string loginName, string password)
        {
            try
            {
                string updatePassword =
                    @"ALTER LOGIN [' + @loginName +'] WITH PASSWORD =  [' + @password +']";
                return context.Database.ExecuteSqlCommand(updatePassword, new SqlParameter("loginName", loginName), new SqlParameter("password", password));
            }
            catch (Exception)
            {  
               return -2;
            }
        }

次に、PASSWORD の近くで sqlException Incorrect syntax を生成します。

Update2

チャーリーからの更新された提案を使用して、QuoteName関数を使用しようとしました

        string sql = @"DECLARE @sql NVARCHAR(500)
              SET @sql = 'ALTER LOGIN ' + QuoteName(@loginName) +
                ' WITH PASSWORD = ' + QuoteName(@password, '''') 
                EXEC @sql";
        return context.Database.ExecuteSqlCommand(sql, new SqlParameter("loginName", loginName), new SqlParameter("password", password));

クエリ文字列が適切に形成されているように見えますが、次の SQLException がスローされます。

編集

もう少し読んだ後、@sqlをラップする構文エラーによってエラーが生成され、エラーなしでクエリを実行できます

 string sql = @"DECLARE @sql NVARCHAR(500)
                  SET @sql = 'ALTER LOGIN ' + QuoteName(@loginName) +
                    ' WITH PASSWORD = ' + QuoteName(@password, '''') 
                    EXEC(@sql)";

補足: 単純に文字列を作成して次のように実行するだけです。

string updatePassword = "USE MASTER ALTER LOGIN [" + loginName + "] WITH PASSWORD =  '" + password + "'";
return context.Database.ExecuteSqlCommand(updatePassword);

上記も回避策であり、SQL ログインを更新します。このコードの実装により、SQL インジェクションの可能性が最小限に抑えられますが、これは最も望ましい方法ではありません。

-ありがとう

4

3 に答える 3

8

レベルでパラメーターを使用する必要がありDbContextます。詳細については、この回答を参照してください。ただし、コード例を次に示します (同じページから適応)。

string sql = "ALTER LOGIN @loginName WITH PASSWORD = @password";
ctx.Database.ExecuteSqlCommand(
    sql,
    new SqlParameter("loginName", loginName),
    new SqlParameter("password", password));

ここ (およびあらゆる場所) でパラメーターを使用する目的は、SQL インジェクション攻撃を防ぐことです。パスワードを変更するコードを書いている場合、これは特に重要です。

アップデート

ALTER LOGIN ステートメントは変数では機能しません。これは、動的 SQL を介して行う必要があります。更新されたコードの例を次に示します。

string sql = @"DECLARE @sql NVARCHAR(500)
               SET @sql = 'ALTER LOGIN ' + QuoteName(@loginName) + 
                    ' WITH PASSWORD= ' + QuoteName(@password, '''') 
               EXEC @sql ";
ctx.Database.ExecuteSqlCommand(
    sql,
    new SqlParameter("loginName", loginName),
    new SqlParameter("password", password));

SQL インジェクション攻撃を防ぐために、まだ SqlParameters を使用していることに注意してください。また、T-SQL メソッドQuoteNameを使用して、生成している SQL で適切な引用を行います。[ただし、このメソッドは、任意の文字 (最初の呼び出し) または'文字 (2 番目の呼び出し) を単純に 2 倍にします。SQL インジェクション攻撃には他にも多くのベクトルがあるため、単に依存するだけでQuoteNameは十分ではありません。

于 2013-02-13T16:27:53.420 に答える
0

上記の回答を Azure SQL で使用していますが、「EXEC @sql」を「EXEC (@sql)」に置き換えるまで、「有効な識別子ではありません」というエラーが表示されました。メッセージ 203、レベル 16、状態 2 は有効な識別子ではありませんを参照してください

さらに、「ALTER LOGIN」の代わりに「ALTER USER」を使用する必要がありました

于 2016-08-02T15:54:32.107 に答える