如何使用变量更改sql登录密码

我正在尝试使用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#app中的代码

 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错误的语法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语法错误。

UPDATE2

使用Charlie的更新建议我试图使用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 *名称’ALTER LOGIN [newuser10] WITH PASSWORD =’t#P @ssw0rd”不是有效的标识符。

编辑

在更多读取之后,错误是由语法错误生成的,包装@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注入的可能性,但这不是最理想的方法。

-谢谢

您需要在DbContext级别使用参数。 有关更多详细信息,请参阅此答案 ,但是,这是一个代码示例(从同一页面改编):

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

在这里(以及在任何地方)使用参数的目的是防止SQL注入攻击。 鉴于您正在编写更改密码的代码,这一点尤其重要。

UPDATE

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)); 

注意我们仍然使用SqlParameters来防止SQL注入攻击。 我们还使用T-SQL方法QuoteName在我们生成的SQL中进行正确的引用; 但是这种方法只是将[字符(在第一个调用中)或'字符(在第二个调用中)加倍。 SQL注入攻击有许多其他向量,因此仅仅依赖QuoteName是不够的。

我在Azure SQL中使用上面的答案,我得到了“非有效标识符”错误,直到我用“EXEC(@sql)”代替“EXEC @sql”。 消息状态2中的消息203,级别16,不是有效的标识符

另外,我不得不使用“ALTER USER”而不是“ALTER LOGIN”