gpt4 book ai didi

c# - 使用Razor MVC + Mysql进行用户身份验证

转载 作者:行者123 更新时间:2023-11-29 05:12:05 25 4
gpt4 key购买 nike

我试图为存储在Mysql数据库中的用户/密码编写一个简单的身份验证函数。问题是我对c不熟悉,所以请原谅我的代码片段中可能出现的任何缺陷。到目前为止我得到的是:
用户注册(测试并将记录保存到数据库):

public User saveUser(User user)
{
MySqlConnection conn = this.connect();

var password = "";
var sha256 = "";
var returnString = "";

var salt = Crypto.GenerateSalt();
sha256 = Crypto.SHA256(user.password);
password = Crypto.HashPassword(salt + sha256);


string sql = "INSERT INTO user(last_name ,first_name, email, password, city_id) "
+ "VALUES (?lastName,?firstName,?email,?password,?cityId); ";

MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Prepare();
cmd.Parameters.Add("?lastName", MySqlDbType.VarChar).Value = user.lastName;
cmd.Parameters.Add("?firstName", MySqlDbType.VarChar).Value = user.firstName;
cmd.Parameters.Add("?email", MySqlDbType.VarChar).Value = user.email;
cmd.Parameters.Add("?password", MySqlDbType.VarChar).Value = password;
cmd.Parameters.Add("?cityId", MySqlDbType.VarChar).Value = user.city.cityId;

try
{
cmd.ExecuteNonQuery();
returnString = "Success";
}
catch (Exception e)
{
returnString = "Error when executing method " + System.Reflection.MethodBase.GetCurrentMethod().Name
+ ". Possible Cause: " + e.Message;
conn.Close();
}

conn.Close();

return new User(user.lastName, user.firstName, user.email,
new City(user.city.cityId, user.city.cityDescription)); }

和用户验证(我认为这不太正确)
public bool authenticateUser(string email, string pass)
{
MySqlConnection conn = this.connect();

var sha256 = Crypto.SHA256(pass);
var hashedPw = Crypto.HashPassword(sha256);

string query = "SELECT u.password FROM user u WHERE u.email = @email AND u.password = @pass";

MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("email ", email);
cmd.Parameters.AddWithValue("password ", hashedPw);

bool output = false;

try
{
int totalCount = Convert.ToInt32(cmd.ExecuteScalar());
if (totalCount == 0)
{
output = true; //login failed
}
else
{
output = false; //login succeeded
}
}
catch (MySqlException e)
{
Console.WriteLine("Error executing method " + System.Reflection.MethodBase.GetCurrentMethod().Name
+ ". Possible Cause: " + e.Message);
}

return output;
}

再次感谢您的帮助。谢谢!!!

最佳答案

我试图为存储在Mysql数据库中的用户/密码编写一个简单的身份验证函数。
首先,一些Internet/编程点会指向您,以便在存储密码时看到使用散列的机会。当我得知人们/公司正在以明文形式存储密码或只是使用加密(谁付钱给这些人)时,这对我来说是一个重大的细微差别!?).
下面,我概述了存储和检索散列密码时需要考虑的要点。
如何存储哈希密码:
这是我在数据库中存储密码的唯一方法-我知道可能还有其他方法-请不要判断。
在数据库中存储User时,需要考虑三件事:
存储Salt,以便以后检索
知道将输入密码和salt连接起来的确切模式,以便首先生成散列(例如salt + inputPassword
存储HashedPassword,以便以后检索
在对新用户的Salt进行哈希运算时,您的想法是正确的。唯一的问题是,您实际上并没有将它存储在任何地方—这对于随后验证用户的凭据至关重要。
更多信息,见下文。
如何检索密码?:
我相信你已经知道了,你唯一知道的关于用户密码的信息就是它的散列,你已经保存在数据库中了。再加上随机生成的salt,你就拥有了一个非常安全的密码。
还记得我关于“将password存储在数据库中”的观点吗;还记得你是如何将这个Salt和原来的Salt放在一起的吗?这就是你需要的地方。
检查登录名和存储的密码是否匹配的唯一方法是运行与创建用户时相同的进程。除了这一次,您没有生成新的Password;而是使用数据库中存储的针对用户的Salt(这就是我们存储它的原因)。
就像这样:
首先,验证用户实际上存在于数据库中(有点明显)并检索数据。
使用它们存储的Salt,将其与它们在生成散列时输入的密码连接起来(在上面的示例中,我使用了salt + inputPassword,因此我们将继续)
然后,可以基于此连接生成哈希:var loginPasswordHash = Crypto.HashPassword(salt + inputPassword);
如果您使用的方法与第一次生成散列时使用的方法完全相同,那么loginPasswordHash应该与数据库中的方法完全相同(前提是它是正确的)-例如if (loginPasswordHash == storedPasswordHash)...
你可以对此进行检查,如果它们匹配,那么你知道它们的密码是正确的;否则,你知道它是错误的
与加密不同,加密是可逆的,使用私钥或纯文本(到底是什么?),您将永远无法从salt和hash中真正找出原始密码是什么。
除非不使用salt,否则使用一些非常整洁的rainbow查找表可以获得密码-散列可能只有一种方法,但每次都会生成相同的最终结果。
如何在代码中应用上述原则:
首先,在创建用户时,您当前没有将生成的salt存储在数据库中。
做吧。
您需要在MySQL表中为Salt添加一个新列。创造它。
保存用户
SaveUser方法中,还要确保将生成的salt保存在数据库中:

...
var salt = Crypto.GenerateSalt();
sha256 = Crypto.SHA256(user.password);
password = Crypto.HashPassword(salt + sha256);


string sql = "INSERT INTO user(last_name ,first_name, email, password, salt, city_id) "
+ "VALUES (?lastName,?firstName,?email,?password,?salt,?cityId); "; // Add 'salt' in here

MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Prepare();
// ...
cmd.Parameters.Add("?password", MySqlDbType.VarChar).Value = password;
cmd.Parameters.Add("?salt", MySqlDbType.VarChar).Value = salt; // Save the 'salt' value
...

认证者
AuthenticateUser方法中,从数据库中检索已知的 User详细信息,以便检查身份验证。
然后,使用生成要存储在数据库中的 password哈希时使用的相同方法,可以使用此方法生成另一个哈希,以便在登录时进行检查:
var salt = user.salt; // Salt from the DB
sha256 = Crypto.SHA256(login.password); // Hash their input password
loginPasswordHash = Crypto.HashPassword(salt + sha256); // Generate a hash of this, just like you did when creating the user

然后,您只需对数据库中的密码运行检查:
var actualHash = user.password; // Get the hashed password from the DB
if (loginPasswordHash == actualHash)
{
// Password is correct
}
else
{
// Password was incorrect
}

最后一句话:
我最不喜欢的就是这个。
当尝试登录时,用户名和/或密码不正确,您会显示什么?
我建议只显示一个错误:
“您提供的登录凭据不正确”
这有助于抵御那些想首先检查潜在用户名有效性的潜在黑客。
嗯,这是一段漫长的旅程。
不过,我希望这对你的项目有帮助:)
当做,
杰夫
更新
尽管上面的示例和对话概述了您最初问题的答案;但这要感谢@zaph指出散列的安全性:
这不太安全,必须对哈希进行迭代以要求最少的CPU时间。使用随机盐在HMAC上迭代大约100毫秒。使用密码哈希、PBKDF2、Bcrypt等函数和类似的函数。关键是让攻击者花费大量时间通过暴力手段查找密码。
请参阅安全堆栈交换上的OWASP(打开Web应用程序安全项目) Password Storage Cheat SheetHow to securely hash passwords, The Theory
有关详细信息,请参见:
Infosec
How I became a password cracker
SecLists
这应该会让任何人相信,仅使用散列保护的密码基本上不提供安全性。我的笔记本电脑每秒可以计算75万HMACs。Salting防止一个破解的散列泄露所有相似的密码
我希望这也能帮助你如何安全地生成散列:)
再次感谢@zaph指出了这一点。

关于c# - 使用Razor MVC + Mysql进行用户身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38063609/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com