2010-09-08 4 views
1

Я все еще изучаю LINQ. Я могу сделать несколько простых запросов, но это немного другое. У меня есть следующий запрос, который аутентифицирует пользователя.Как использовать 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 
      } 

ответ

6

Вы не должны указывать, если имя пользователя было правильным или указать, что Pasword было неправильным, «Неверное имя пользователя или пароль» должно быть достаточно. И общий для большинства систем.

Это дает вам проверку статуса, если комбинация имени пользователя и пароля верна, после чего у вас есть запись пользователя, и вы можете проверить статус на этом.

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 
} 
+0

Я согласен с тем, что вы должны показывать только диалоговое окно «Неверное имя пользователя или пароль». Но это для ведения журнала. И обычный пользователь не имеет прав на чтение журнала. – bsh152s

+0

@ bsh152s, следуя тому же подходу, я добавил пример, который обеспечит требуемую детализацию. –

+0

Спасибо, вот что я пришел после прочтения вашего первого ответа. Наверное, я немного переусердствовал. – bsh152s

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; 
} 
Смежные вопросы