我还在学习LINQ。我可以做一些简单的查询,但这个有点不同。我有以下查询来验证用户。
User user = (from u in db.Users
where u.Username.Equals(username) &&
u.Password.Equals(UserSecurity.GetPasswordHash(username, password)) &&
u.Status == true
select u).FirstOrDefault();
这有效但现在我需要记录登录失败的原因。如果用户名无效,我会记录一件事。如果密码错误,我会记录另一个。或者,如果用户处于非活动状态(status = false),那么我将记录另一个用户。我意识到我可以把它分成3个单独的查询来找出失败的东西,但我想知道在一个中做这个会更有效。如果是这样,怎么样?这是我的(未经测试的)3查询方法。
User user2 = null;
var users1 = db.Users.Where(i => i.Username.Equals(username));
if (users1 != null)
{
var users2 = users1.Where(i => i.Password.Equals(UserSecurity.GetPasswordHash(username, password)));
if (users2 != null)
{
var users3 = users2.Where(i => i.Status);
if (users3 != null)
{
user2 = users3.FirstOrDefault();
}
else
{
// User inactive
}
}
else
{
// Password invalid.
}
}
else
{
// Username invalid
}
答案 0 :(得分:9)
您不应指定用户名是否正确或指定密码错误,“无效的用户名或密码”应该足够。并且对大多数系统来说都很常见。
这使您可以检查状态,如果用户名/密码组合正确,则返回用户记录,您可以从中检查状态。
User user = (from u in db.Users
where u.Username.Equals(username) &&
u.Password.Equals(UserSecurity.GetPasswordHash(username, password))
select u).FirstOrDefault();
if (user == null)
{
// Invalid user name or password
}
else if (user.Status != true)
{
// User inactive
}
else
{
// Success
}
如果您必须指出无效用户名与无效密码之间的区别,您可以执行以下操作。
User user = (from u in db.Users
where u.Username.Equals(username)
select u).FirstOrDefault();
if (user == null)
{
// Invalid user name
}
else if (!user.password.Equals(...))
{
// Invalid password
}
else if (user.Status != true)
{
// User inactive
}
else
{
// Success
}
答案 1 :(得分:1)
在这种情况下,我不认为仅使用Linq“使用linq”。
话虽如此,我确实使用字节数组的扩展方法SequenceEqual
来比较两个哈希密码。我通常将我的密码存储为数据库中的二进制文件(64)(以及盐二进制文件(16))
这是我验证密码的典型方法(或多或少)。我将其修改为包含Linq搜索,例如您的示例
public bool AuthenticateUser(string username, string password)
{
// I don't validate password here (see TODO below)
var user = db.User.FirstOrDefault(u => u.UserName == username && u.Status);
if(user != null)
{
var rehash = Hashing.Hash(password, user.PasswordSalt); // PasswordSalt is a byte array
if(rehash.SequenceEqual(user.Password))
{
return true;
}
else
{
Logger.LogUnsuccessfulAuthentication(user);
// TODO: Increase user-login failure count and system-wide failure count
}
}
return false;
}