0

这方面的新...

提供者(我假设是他们的代码)设置了一个存储过程来修改用户的 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])手动执行时,它当然可以完美运行。

4

1 回答 1

0

这是由于 Sql Server 如何处理 sysname 类型的参数值。考虑一下。

create procedure TakeSysname
    @Sysname sysname
as
    --does nothing;
go

--This works.
exec TakeSysname JohnDoe;
print N'Worked';
go

--This works.
exec TakeSysname 'John.Doe';
print N'Worked'
go

--This does not.
exec TakeSysname John.Doe;
print N'Worked';
go

不过,我仍在寻找一些好的解释。

于 2015-08-06T06:14:34.703 回答