如何使用linq验证用户名/密码?

时间:2010-09-08 01:46:37

标签: c# linq authentication

我还在学习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
            }

2 个答案:

答案 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;
}