2010-11-11 28 views
1

在ASP.NET应用程序中,我使用md5将密码保存为数据库的“二进制”数据。使用md5以二进制形式保存和比较数据库密码

我该如何比较密码?

我用code in this article to encrypt the password with md5

的代码工作。当用户在登录时输入密码时,如何比较密码?检查密码是否与数据库中的加密密码相匹配的代码是什么?

我用下面的代码,但它总是显示“不正确的用户名或密码”,即使它是正确的。“该modifird代码”

Byte[] hashedBytes; 
    string Password = txtPassword.Text; 
    MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); 
    UTF8Encoding encoder = new UTF8Encoding(); 

    hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Password)); 
    Byte[] pass = new Byte[16]; 
    SqlConnection conn = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin"); 

    SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE [email protected]", conn); 
    cmd.Parameters.AddWithValue("@UserName", txtUserName.Text); 
    conn.Open(); 
    SqlDataReader rdr = cmd.ExecuteReader(); 
    if (rdr.Read()) 
     pass = (Byte[])rdr["password"]; 

    foreach (Byte b in pass) 
    { 
     Label1.Text += b.ToString() + " "; 



     //Response.Write(b.ToString()); 

     string UserName = txtUserName.Text; 
     bool isMatch = false; 
     Byte[] password = new Byte[16]; 

     SqlConnection con = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin"); 
     con.Open(); 

     SqlCommand cmdd = new SqlCommand(string.Format("select * from Users where UserName='{0}'", UserName), con); 
     cmd.CommandType = CommandType.Text; 
     cmd.Parameters.AddWithValue("@UserName", txtUserName.Text); 
     SqlDataReader dr = cmdd.ExecuteReader(); 
     if (dr.Read()) 
     { 
      password = (Byte[])dr["Password"]; 
     } 
     foreach (Byte c in password) 
     { 
      Label2.Text += c.ToString() + " ";//I didnt close the pracket fo that reason data is repeted if I close it I cant type c.toString 



      while (dr.Read()) 
      { 

       if (b.ToString() == c.ToString()) // I mean this statment 
       { 
        isMatch = true; 
       } 
      } 
     } 




     dr.Close(); 
     con.Close(); 

     if (isMatch) 
     { 
      Response.Write("correct"); 
     } 
     else 
     { 
      Response.Write("Incorrect username or password!"); 
     } 

    } 

编辑的代码 保护无效的button1_Click(对象发件人,EventArgs的) { } public static bool ValidateUser(string userName,string password) {SqlConnection con = new SqlConnection(“Data Source = shihab-PC; Initial Catalogue = test; User ID = sh; password = admin”); con.Open();

using (var connection = new SqlConnection("connectionString")) 
    using (var command = connection.CreateCommand()) 
    { 
     command.CommandText = "SELECT dbo.checkUserExists (@userName, @password)"; 
     command.Parameters.Add("@userName", SqlDbType.NVarChar, 25).Value = userName; 
     command.Parameters.Add("@password", SqlDbType.NVarChar).Value = GenerateHash(password); 

     connection.Open(); 
     return (bool)command.ExecuteScalar(); 
    } 
} 

private static string GenerateHash(string value) 
{ 
    return Convert.ToBase64String(new System.Security.Cryptography.HMACSHA1(Encoding.UTF8.GetBytes("salt")).ComputeHash(Encoding.UTF8.GetBytes(value))); 
} 

}

+0

MD5不加密;没有办法解密,缺乏暴力或MD5的弱点。 MD5是一个散列;许多不同的输入可以产生相同的散列输出。 – 2010-11-11 18:44:28

+1

还有一些事情:1)MD5坏了;使用SHA-1或(更好)SHA-2。 2)每行使用不同的盐。 – 2010-11-11 18:45:31

+0

我不想解密,我只是想比较用户输入的密码和存储在数据库中的密码 – shihab 2010-11-11 20:15:15

回答

4

当你比较密码 - 你需要计算他们所提交的密码MD5。

因此,在你的代码,你想是这样的:

MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); 
//create an array of bytes we will use to store the encrypted password 
Byte[] hashedBytes; 
//Create a UTF8Encoding object we will use to convert our password string to a byte array 
UTF8Encoding encoder = new UTF8Encoding(); 

//encrypt the password and store it in the hashedBytes byte array 
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(txtPassword.Text)); 

//set the password they are using now to password for the compare: 
Password = hashedBytes; 

然后在这之后,你可以运行比较代码。问题的关键是,在数据库中的密码,当他们签署了

编辑你计算原hashedBytes:这里是你的原代码:

SqlConnection con = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin"); 
con.Open(); 
string UserName = txtUserName.Text; 
string Password = txtPassword.Text; 

//hash password 
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); 
Byte[] hashedBytes; 
UTF8Encoding encoder = new UTF8Encoding(); 
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Password)); 
Password = hashedBytes.ToString(); 

bool isMatch = false; 
SqlCommand cmdd = new SqlCommand(string.Format("select * from Users where UserName='{0}'", UserName),con); 
SqlDataReader dr = cmdd.ExecuteReader(); 
while (dr.Read()) 
{ 
    if (dr["password"].ToString()==Password) 
    { 
     isMatch = true; 
    } 
} 
dr.Close(); 
con.Close(); 
if (isMatch) 
{ 
    Response.Write("correct"); 
} 
else 
{ 
    Response.Write("Incorrect username or password!"); 
} 

更新的代码转换错误

试试这个代码即可查看密码这将打印出被散列密码,并在数据库中的密码 - 如果它们不匹配你有问题(可能是盐问题)

Byte[] hashedBytes; 
string Password = txtPassword.Text; 
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); 
UTF8Encoding encoder = new UTF8Encoding(); 
hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Password)); 

Response.Write(string.Format("Hashed Password (Given): {0}<br />", hashedBytes.ToString())); 

string UserName = txtUserName.Text; 
SqlConnection con = new SqlConnection("Data Source=Shihab-PC;Initial Catalog=test;User ID=sh;password=admin"); 
con.Open(); 

SqlCommand cmdd = new SqlCommand(string.Format("select * from Users where UserName='{0}'", UserName),con); 

SqlDataReader dr = cmdd.ExecuteReader(); 

//should be only one row.. 
while (dr.Read()) 
{ 
    Response.Write(string.Format("Hashed Password (DB): {0}", dr["password"].ToString())); 
} 
dr.Close(); 
con.Close(); 
+0

可以在下面解释细节我不知道在哪里添加你的代码确切地。第88行中的 – shihab 2010-11-11 19:57:51

+0

错误:Password = hashedBytes; //编译器错误消息:CS0029:不能隐式地将类型'byte []'转换为'字符串' – shihab 2010-11-12 10:00:00

+2

现在我觉得你不是在尝试... – Prescott 2010-11-12 10:27:05

0

C#代码:

public static bool ValidateUser(string userName, string password) 
{ 
    using (var connection = new SqlConnection("connectionString")) 
    using (var command = connection.CreateCommand()) 
    { 
     command.CommandText = "SELECT dbo.checkUserExists (@userName, @password)"; 
     command.Parameters.Add("@userName", SqlDbType.NVarChar, 25).Value = userName; 
     command.Parameters.Add("@password", SqlDbType.NVarChar).Value = GenerateHash(password); 

     connection.Open(); 
     return (bool)command.ExecuteScalar(); 
    } 
} 

private static string GenerateHash(string value) 
{ 
    return Convert.ToBase64String(new System.Security.Cryptography.HMACSHA1(Encoding.UTF8.GetBytes("salt")).ComputeHash(Encoding.UTF8.GetBytes(value))); 
} 

SQL存储过程:

IF OBJECT_ID(N'checkUserExists', N'FN') IS NOT NULL 
DROP FUNCTION checkUserExists 
GO 
CREATE FUNCTION checkUserExists 
(
    @userName NVARCHAR(25), 
    @password NVARCHAR(255) 
) 
RETURNS BIT 
AS 
BEGIN 
    RETURN ISNULL((
     SELECT 1 
     FROM users 
     WHERE 
      name = @userName 
     AND password = @password 
    ), 0) 
END 
+0

参见http://stackoverflow.com/questions/1300890/md5-hash-with-salt-for-keeping-password-in -db-in-c – abatishchev 2010-11-14 09:36:29

+0

仍然存在错误。 – shihab 2010-11-14 11:37:51

+0

@shihab:哪里和什么? – abatishchev 2010-11-14 14:11:27

1

这是代码,我从你的代码调整,it's工作正常(被字节比较字节从存储密码在db与当前密码给用户):

 public bool AddNewUser(string userId, string pwd, string dept,string mail,string displayName) 
    { 
     //get the username  
     string UserName = userId; 

     SqlConnection conn = new SqlConnection(GetConnectionString());  //sql command to add the user and password to the database  
     SqlCommand cmd = new SqlCommand("INSERT INTO MAIN_USER_DATA(USERID, PWD,DEPARTMENT,MAIL,DISPLAY_NAME) VALUES (@USERID, @PWD,@DEPARTMENT,@MAIL,@DISPLAY_NAME)", conn);  
     cmd.CommandType = CommandType.Text;  //add parameters to our sql query  
     cmd.Parameters.AddWithValue("@USERID", UserName); 
     cmd.Parameters.AddWithValue("@PWD", GenerateHash(userId ,pwd)); 
     cmd.Parameters.AddWithValue("@DEPARTMENT", dept); 
     cmd.Parameters.AddWithValue("@MAIL", mail); 
     cmd.Parameters.AddWithValue("@DISPLAY_NAME", displayName); 
     using (conn) {  //open the connection  
      conn.Open();  //send the sql query to insert the data to our Users table 
      try 
      { 
       cmd.ExecuteNonQuery(); 
       return true; 
      } 
      catch 
      { 
       return false; 
      } 
     } 

    } 
    public bool ValidateUser(string userId, string password) 
    { 
     using (SqlConnection connection = new SqlConnection(GetConnectionString())) 
     using (SqlCommand command = connection.CreateCommand()) 
     { 
      command.CommandText = "SELECT PWD FROM MAIN_USER_DATA WHERE [email protected]"; 
      command.Parameters.Add("@USERID", SqlDbType.NVarChar, 25).Value = userId; 
      connection.Open(); 
      SqlDataReader dr = command.ExecuteReader(); 
      if (dr.Read()) 
      { 
       byte[] storedPwd = (byte[])dr["PWD"]; 
       byte[] currentPwd = GenerateHash(userId, password); 
       for (int i = 0;i< storedPwd.Length; i++) 
       { 
        if (storedPwd[i] != currentPwd[i]) 
        { 
         return false; 
        } 
       } 
      } 
      else 
       return false; 
      return true; 
     } 
    } 
    private byte[] GenerateHash(string userId, string password) 
    { 
     //create the MD5CryptoServiceProvider object we will use to encrypt the password  
     HMACSHA1 hasher = new HMACSHA1(Encoding.UTF8.GetBytes(userId));    //create an array of bytes we will use to store the encrypted password  
     //Byte[] hashedBytes; //Create a UTF8Encoding object we will use to convert our password string to a byte array  
     UTF8Encoding encoder = new UTF8Encoding();  //encrypt the password and store it in the hashedBytes byte array  
     return hasher.ComputeHash(encoder.GetBytes(password));  //connect to our db 
    } 
相关问题