【发布时间】:2015-03-28 21:16:53
【问题描述】:
我正在编写一个使用 2008 SQL Server 数据库的旧式 ColdFusion 应用程序。我对如何设置 SQL Server 数据库知之甚少,但我希望如果我分享一些症状,有人可能会对检查内容提出一些建议。
数据库使用对称密钥来保护用户密码。我有一个用户表,其中包含用户名、密码等作为字段。密码已加密。
数据库中的大多数旧用户都可以正常工作。用户可以毫无问题地使用网站登录、更改密码等。对于用于测试的记录,我在 SQL Server 中使用 SQL 更改了密码,而不是通过网站:“update users set password = "fluffy" where userID in (6543, 7654, 8765)”等。
当我这样做时,会发生一些事情:
我第一次使用 USERID 6543 永远无法登录网站 和密码“蓬松”——但它总是在第二次工作。
当我运行存储过程
exec get_user_unencrypt_by_id 6543时,
结果返回“NULL”作为密码。当我运行查询
select * from Users时,我看到了预期的
大多数密码字段中的符号/乱码,但对于用户
6543、7654、8765,我看“毛茸茸”的。当我运行查询
select * from users where password is null时,我得到 没有结果。
我为解决问题所做的工作:
我运行以下 SQL 来打开和重置主密钥:
OPEN MASTER KEY DECRYPTION BY PASSWORD = ''
ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY
Close Master Key
GO
这似乎没有效果。
我尝试使用 SQL 更新损坏的密码
update users set password = EncryptByKey(Key_GUID('PASS_Key_01'), 'fluffy')
where userID in (6543, 7654, 8765)"
当我尝试这样做时,这些用户在使用密码“fluffy”时被锁定了。
我已尝试通过网站重置密码。这似乎仅适用于密码未损坏的记录。如果我使用其中一个损坏的密码执行此操作,它似乎可以暂时工作,但稍后(第二天),密码再次损坏。
我的名为 get_user_unencrypt_by_id 的 SP 是这样的:
OPEN SYMMETRIC KEY PASS_Key_01
DECRYPTION BY CERTIFICATE UserPasswords0324
SELECT userid, username, CONVERT (nvarchar,
DecryptByKey([password])) as 'password', [role], firstname, lastname,
Add1, Add2, City, [State], Zip, Phone, Fax,
FROM users
我不确定还可以尝试什么,所以我很乐意为您提供任何建议或想法。谢谢。
已编辑以添加更多细节。在继续调查中,我了解到桌子上有一个触发器。这是触发器。
/****** Object: Trigger [dbo].[encrypt_password_on_update]
Script Date: 4/1/2015 8:55:44 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[encrypt_password_on_update]
ON [dbo].[USERS]
after update
AS
BEGIN
/***The purpose of this trigger is to encrypt a password that was
update by the user. When the update statement updates the password,
this encrypts it before storing it in the db***/
DECLARE @updatecount int
DECLARE @userid int
DECLARE @password nvarchar(50)
DECLARE @temp_encryt_password nvarchar(50)
select @updatecount = (select count(userid) from inserted)
if (@updatecount = '1')
BEGIN
SELECT @userid = (SELECT userid FROM Inserted)
OPEN SYMMETRIC KEY PASS_Key_01
DECRYPTION BY CERTIFICATE UserPasswords0324
if (@userid != '' and @userid is not null)
BEGIN
select @temp_encryt_password = (select
EncryptByKey(Key_GUID('PASS_Key_01'), [password]) from users where
userid = @userid)
/***If the password is already encrypted (if the update was for something else other than the password) we don't want to reencrypt***/
if ( CONVERT (nvarchar, DecryptByKey(@temp_encryt_password)) is not null)
BEGIN
update USERS
set [password] = EncryptByKey(Key_GUID('PASS_Key_01'), [password])
where userid = @userid
END
END
END
END
GO
【问题讨论】:
-
您的示例中的密码永远不会为空,
exec get_user_unencrypt_by_id 6543在无法成功时只是简单地返回null,这就是select...where null失败的原因。 -
谢谢。我认为这是有道理的。不过,它存储的不是密码,我不知道它是什么。我还没有解决这个问题,所以我欢迎其他关于寻找什么的建议。
-
但稍后(第二天),密码再次损坏发生这种情况时的确切事件链是什么以及“密码”列的值是什么每一步?跟踪这些可以帮助您弄清楚发生了什么,例如值是否被双重加密......请记住,您可以将值记录到另一个表inside触发器以进行调试。即步骤1)您重置密码2)用户通过应用程序登录3)用户通过应用程序更改密码4)用户使用新密码再次登录5)......?
-
也就是说,为什么要加密密码? Typically hashing is preferred.
-
我相信通过网站更新密码 - 分别通过业务逻辑/api创建密码的哈希值,然后将其存储在数据库中。这就是为什么当直接更新时,你会得到简单英语的 'fluffy' 字符串。在将其存储在数据库中之前,您必须使用对其进行哈希处理的函数。您可能需要检查是否存在更新用户密码的存储过程。 update_user_password_by_id 之类的东西
标签: sql-server encryption coldfusion