我有一个应测试登录的代码。当我从字面上执行时,它可以正常工作,返回一排(预计)。当我在sqlcommand上使用参数时,我没有任何行。
它有效(用户名和密码的文字值):
string strConn = 'string connection';
SqlConnection conn = new SqlConnection(strConn);
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = conn;
sqlCommand.Parameters.Clear();
sqlCommand.CommandText = @"select *
from
Usuario
where
Username = 'test' and
Password = CONVERT(VARCHAR(32), ashBytes('MD5', 'test'), 2)";
conn.Open();
SqlDataReader ret = sqlCommand.ExecuteReader();
但它不起作用(用户名和密码的参数值):
string strConn = 'string connection';
SqlConnection conn = new SqlConnection(strConn);
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = conn;
sqlCommand.Parameters.Clear();
sqlCommand.CommandText = @"select *
from
Usuario
where
Username = @login and
Password = CONVERT(VARCHAR(32), ashBytes('MD5', @pass), 2)";
SqlParameter user = new SqlParameter("@login", SqlDbType.NVarChar, 50) { Value = "test" };
SqlParameter pass = new SqlParameter("@pass", SqlDbType.NVarChar, 50) { Value = "test" };
List<SqlParameter> list = new List<SqlParameter>();
list.Add(user);
list.Add(pass);
sqlCommand.Parameters.AddRange(list.ToArray<SqlParameter>());
conn.Open();
SqlDataReader ret = sqlCommand.ExecuteReader();
我没有Sintax错误或类似的错误。第二个代码只是不返回行。我尝试使用sqlcommand.parameters.addwithvalue,但我也没有成功。
'test'
和 N'test'
将它们转换为哈希时不是同一回事。一个是ASCII,另一个是Unicode。如果它们都是ASCII,则在您的参数中使用SqlDbType.VarChar
(不是SqlDbType.NVarChar
)。
sql
中说明的差异DECLARE @passUnicode Nvarchar(100) = N'test'
DECLARE @passAscii varchar(100) = 'test'
SELECT CONVERT(VARCHAR(32), HashBytes('MD5', @passAscii), 2) AS [Md5OfAscii]
, CONVERT(VARCHAR(32), HashBytes('MD5', @passUnicode), 2) AS [Md5OfUnicode]
结果
098F6BCD4621D373CADE4E832627B4F6, C8059E2EC7419F590E79D7F1B774BFE6
侧注
密码哈希
我建议不要将密码存储为MD5,MD5根本不安全。那里有很多替代方案,例如pbkdf2
,bcrypt
和scrypt
,可以命名一些更普遍接受的安全密码散列算法。
C#结构
使用ado.net(或与此相关的任何资源)时,应包装连接,数据标准,适配器等,以在using
块中实现IDisposable
。这将确保即使在连接的情况下,也将始终释放外部资源。
string connectionString = "";
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand
{
CommandText = @"select * from Usuario where Username = @login and Password = CONVERT(VARCHAR(32), HASHBYTES('MD5', @pass), 2)",
CommandType = CommandType.Text,
Connection = connection
})
{
command.Parameters.Add(new SqlParameter("login", SqlDbType.VarChar, 50) { Value = "test" });
command.Parameters.Add(new SqlParameter("pass", SqlDbType.VarChar, 50) { Value = "test" });
connection.Open();
using (var dataReader = command.ExecuteReader())
{
// do some stuff
}
}
}