2013-02-13 45 views
4

我试图更新使用ALTER LOGIN为现有的SQL登录密码如何更改与变量SQL登录密码

我知道了以下工作

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

然而,当我尝试使用局部变量

DECLARE @newpass nvarchar(max); 
SET @newpass = '[email protected]'; 
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 = '[email protected]'; 
DECLARE @hashedpass varbinary(max); 
SET @hashedpass = HASHBYTES('SHA1', CONVERT(nvarchar(max),@newpass)); 

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

谁能帮助我了解如何更新在s中登录密码ql使用变量而不是固定值?

在此先感谢

更新

基于从查理建议我也试过以下

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新的语法“@密码”。 如果我振奋参数

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不正确的语法。

UPDATE2

使用从查理更新的建议,我尝试虽然看起来查询字符串正确地形成了以下则抛出SQLException *名称使用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)); 

'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注入的可能性,但这并不是最理想的方法。

-Thanks

+1

究竟它是如何失败的?你是否收到错误信息? – 2013-02-13 16:24:04

+0

如果你只是用PASSWORD = @newpass运行ALTER LOGIN [用户名]在c#中运行上面的代码块会捕获相同的异常,因为它正在从sql查询中冒泡 – rlcrews 2013-02-13 16:27:31

回答

6

您需要在DbContext级别使用的参数。详情请参阅this answer,但是,这里有一个代码示例(改编自同一页):

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是不够的。

+1

sp_password被注意为在将来的SQL Server版本中被删除,并且它们指向您使用ALTER LOGIN http://msdn.microsoft.com/en-us/library/ms174428.aspx。我只知道因为我先去了那里;) – 2013-02-13 16:29:16

+0

哈!我没有意识到,我会相应地更新我的答案。 – 2013-02-13 16:29:50

+1

感谢查理我会给这个尝试我是避免基于它将被弃用的sp_password。我知道这将是一个出路,但我是按照MSDN的建议 – rlcrews 2013-02-13 16:30:24

0

我对Azure SQL使用上述答案,直到我将“EXEC @sql”替换为“EXEC(@sql)”时,我才得到“无效标识符”错误。见Msg 203, Level 16, State 2, is not a valid identifier

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