我试图让哈希为密码工作。他们目前没有进行调试,无法进行调试。
目前我使用的哈希算法是SHA1
。
我的表格(称为Users
)包括:
[phone] varchar(32)
[password] binary(20)
要填充我的数据库,我使用此查询:
DELETE FROM Users
INSERT INTO Users (phone, password)
VALUES ('0526487612', HASHBYTES(SHA1, 'admin123'))
当我登录时,我这样做:
command = connection.CreateCommand();
command.CommandText = "SELECT * FROM Users WHERE phone=@UName AND password=HASHBYTES('SHA1', @PWord)";
command.Parameters.AddWithValue("@UName", username);
command.Parameters.AddWithValue("@PWord", password);
reader = command.ExecuteReader();
if (reader.HasRows)
{
// ...
}
当我尝试登录时(使用用户名0526487612
和密码admin123
),它永远不会进入if(...)
(意味着读者找不到任何匹配的行)查询)。
如果我不填写密码,一切都有效 - 这意味着问题不在其他地方。
我尝试使用不同的哈希算法(SHA2_256
)并相应地更改SQL Server数据类型(binary(32)
),但结果是一样的。
我正在使用Microsoft SQL Server 2014;我不知道如何进一步调试。
答案 0 :(得分:3)
我个人认为,当您直接从SQL Server Management Studio运行查询并运行以下语句时:
DELETE FROM Users;
INSERT INTO Users (phone, password)
VALUES ('0526487612', HASHBYTES('SHA1', 'admin123'));
您的密码(admin123
)是VARCHAR
。现在,当您执行代码时,它不会像那样执行:
SELECT * FROM Users WHERE phone=@UName AND password=HASHBYTES('SHA1', @PWord);
相反,它执行此语句(您的参数以NVARCHAR
发送):
EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', @p1)'
, N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
, @p0 = N'0526487612'
, @p1 = N'admin123';
将@p1
(您的密码)转换为VARCHAR
可以解决问题。
EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', CAST(@p1 AS VARCHAR(30)))'
, N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
, @p0 = N'0526487612'
, @p1 = N'admin123';
运行此证明NVARCHAR
输出不同的二进制文件:
SELECT HASHBYTES('SHA1', 'admin123') AS VarcharSHA1
, HASHBYTES('SHA1', N'admin123') AS nVarcharSHA1;
结果:
VarcharSHA1 nVarcharSHA1
--------------------------------------------------------------------------------------
0xF865B53623B121FD34EE5426C792E5C33AF8C227 0xB7BC3A1B04D9E165C6762B0A1CDE5226DF5B6A6A
完整示例:
IF OBJECT_ID('Users', 'U') IS NOT NULL
DROP TABLE Users;
CREATE TABLE Users
(
[phone] VARCHAR(30)
, [password] BINARY(20)
);
INSERT INTO Users ([phone], [password])
VALUES ('0526487612', HASHBYTES('SHA1', 'admin123'));
EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', @p1)'
, N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
, @p0 = N'0526487612'
, @p1 = N'admin123';
-- Doesn't bring result back
EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', CAST(@p1 AS VARCHAR(30)))'
, N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
, @p0 = N'0526487612'
, @p1 = N'admin123';
-- Brings results back
TRUNCATE TABLE Users;
INSERT INTO Users ([phone], [password])
VALUES ('0526487612', HASHBYTES('SHA1', N'admin123'));
-- ^
-- |
-- Notice this
EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', @p1)'
, N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
, @p0 = N'0526487612'
, @p1 = N'admin123';
-- Brings results back
EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', CAST(@p1 AS VARCHAR(30)))'
, N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
, @p0 = N'0526487612'
, @p1 = N'admin123';
-- Doesn't bring result back
所以我已经指出了问题,现在由你决定如何修复它。要么总是将密码转换为VARCHAR
,要么在对其进行散列时使用等效的unicode。
显然你没有插入密码并将其哈希为NVARCHAR
,但是你必须稍微修改你的c#代码以传递你想要的值数据类型,而不是数据类型ADO.NET自己选择。请阅读这篇文章:Can we stop using AddWithValue() already?了解更多信息。
基于此,您可以像这样更新代码,它应该可以正常工作:
command = connection.CreateCommand();
command.CommandText = @"
SELECT *
FROM Users
WHERE phone = @UName
AND password = HASHBYTES('SHA1', @PWord)";
//Add parameters like that and it will pass in correct data type
command.Parameters.Add("@UName", SqlDbType.VarChar, 50).Value = username;
command.Parameters.Add("@PWord", SqlDbType.VarChar, 50).Value = password;
//command.Parameters.AddWithValue("@UName", username);
//command.Parameters.AddWithValue("@PWord", password);
reader = command.ExecuteReader();
if (reader.HasRows)
{
// ...
}