这方面的新...
提供者(我假设是他们的代码)设置了一个存储过程来修改用户的 SQL 服务器密码。他们使用 sysname 类型来传递信息:OLD、NEW 和 LOGINAME。
当他们执行更改密码的命令时,他们使用 quotename() 将传递给函数的文本括起来。
在此之前,在检查用户名是否存在时,他们通过 LOGINAME 而不进行任何格式控制。
这在过去不是问题,但由于我们最近将用户名策略从名字首字母+姓氏 (FSURNAME) 更改为名字(点)姓氏 (FIRST.SURNAME),因此例程崩溃了。我认为这是因为在传递给 see-if-they-exist 函数时缺少对用户名的 quotename() 样式控制。
代码:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [sys].[sp_password]
@old sysname = NULL, -- the old (current) password
@new sysname, -- the new password
@loginame sysname = NULL -- user to change password on
as
-- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --
set nocount on
declare @exec_stmt nvarchar(4000)
-- RESOLVE LOGIN NAME
if @loginame is null
select @loginame = suser_sname()
if @new is null
select @new = ''
-- DISALLOW USER TRANSACTION --
set implicit_transactions off
IF (@@trancount > 0)
begin
raiserror(15002,-1,-1,'sys.sp_password')
return (1)
end
-- CHECK IT'S A SQL LOGIN --
if not exists (select * from master.dbo.syslogins where
loginname = @loginame and isntname = 0)
begin
raiserror(15007,-1,-1,@loginame)
return (1)
end
if @old is null
set @exec_stmt = 'alter login ' + quotename(@loginame) +
' with password = ' + quotename(@new, '''')
else
set @exec_stmt = 'alter login ' + quotename(@loginame) +
' with password = ' + quotename(@new, '''') + ' old_password = ' + quotename(@old, '''')
exec (@exec_stmt)
if @@error <> 0
return (1)
-- RETURN SUCCESS --
return (0) -- sp_password
我强烈怀疑这里的代码:
if not exists (select * from master.dbo.syslogins where
loginname = @loginame and isntname = 0)
导致问题,据我了解,代码将 FIRST.LAST 传递给检查例程,然后将其解释为对象而不是文本。
是否可以做同样的事情但强制发送文本?类似于代码中其他地方使用的 quotename() 函数?
编辑:
执行此存储过程的调用:sp_password NULL、abcdefgh、FIRST.LAST
收到错误:消息 102,级别 15,状态 1,第 1 行 '.' 附近的语法不正确。
当通过添加括号(sp_password NULL, abcdefgh, [FIRST.LAST])手动执行时,它当然可以完美运行。