2016-11-12 56 views
2

下面的代码是不工作:创建sp_executesql的PROC SQL登录

declare @pUserName nvarchar(50) = N'[test2]' ; 
declare @pPassword nvarchar(50) = N'''123456'''; 

declare @QueryString as nvarchar(max); 
declare @ParmDefinition as nvarchar(max); 

SET @QueryString = N'CREATE LOGIN @dUserName WITH PASSWORD= @dpassword , DEFAULT_DATABASE=[Yerknain] ,DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=ON, CHECK_POLICY=ON'; 
SET @ParmDefinition = N'@dUserName nvarchar(50) , @dpassword nvarchar(50)'; 

EXECUTE sp_executesql @QueryString, @ParmDefinition, 
          @dUserName = @pUserName, 
          @dpassword = @pPassword; 

它抛出一个错误:

Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '@dUserName'.

,但是当我把它改成如下:

declare @pUserName nvarchar(50) = N'test2' ; 
declare @pPassword nvarchar(50) = N'123456'; 

declare @QueryString as nvarchar(max); 
declare @ParmDefinition as nvarchar(max); 

SET @QueryString = N'CREATE LOGIN [@dUserName] WITH PASSWORD= ''@dpassword'' , DEFAULT_DATABASE=[Yerknain] ,DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=ON, CHECK_POLICY=ON'; 
SET @ParmDefinition = N'@dUserName nvarchar(50) , @dpassword nvarchar(50)'; 

EXECUTE sp_executesql @QueryString, @ParmDefinition, 
          @dUserName = @pUserName, 
          @dpassword = @pPassword; 

它正在工作,但不是注册名为“test2”的新用户,而是使用名称“@pUserName”注册它。

有没有什么办法可以解决这个问题sp_executesql程序(不只是通过exec,我需要检查一切)?

回答

2

尝试使用字符串连接像这样构建@QueryString。请注意,这样做时,您不需要将这些参数作为参数发送到sp_executesql

SET @QueryString = N'CREATE LOGIN '+QUOTENAME(@dUserName)+' WITH PASSWORD= '''+REPLACE(@dpassword,'''','''''')+''' , DEFAULT_DATABASE=[Yerknain] ,DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=ON, CHECK_POLICY=ON'; 
+0

但通过这种方式,参数将不会被检查,无论他们是否在确切的长度或类型,它只会把它放在那里,而不检查是?所以存在SQL注入的风险?或者从安全方面来说没问题? –

+1

@AlphasSupremum **(1)**通过在矩形括号之间放置用户名,并用密码中的两个单引号('''')替换单引号(''')的任何实例,您将受到保护来自SQL注入攻击。 **(2)**您无法使用参数创建登录名,这就是为什么我的答案将字符串中的用户名连接起来。不过,我不确定密码是否可以作为参数传递,你应该尝试看看是否有效。无论如何,我写的是安全的与SQL注入攻击。 –

+1

@AlphasSupremum我修改了我的答案以使用['QUOTENAME'](https://msdn.microsoft.com/nl-be/library/ms176114.aspx)函数,这是一个更好的防范SQL注入的功能案件。引用自己的名字通常不是一个好主意。 'QUOTENAME'函数总是能够做到最好。 –