Реализация логина пользователя, вопрос JDBC транзакций - PullRequest
1 голос
/ 25 февраля 2011

У меня есть вопрос, касающийся транзакций базы данных, когда я не уверен, правильно ли я понимаю.Я хочу реализовать логин пользователя в Java-приложении.Поскольку в одной и той же базе данных может быть несколько серверов, и каждый пользователь может войти в систему только на одном из этих серверов, база данных должна сохранять флаг, если пользователь уже вошел в систему.

Итак, предположим следующую структуру таблицы:

ID | User | PWD | Server

, где Server - это ссылка на сервер, на котором пользователь вошел в систему, или NULL, если он не вошел в систему.

Когда пользователь входит в систему,Я должен сначала проверить, является ли значение сервера NULL, и если нет, установить его в соответствующее ссылочное значение.Но что происходит, когда между этими двумя утверждениями пользователь входит в систему на другом сервере?Может ли такое состояние быть обнаружено транзакциями?например (псевдо)

conn.setAutoCommit(false);
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM users WHERE user = 'usr' AND password = 'pwd'");
if (rs.next()) {
  rs.getInt("Server");
  if (rs.wasNull()) {
    // Not logged in
    conn.createStatement().execute("UPDATE users SET server = 123 WHERE user = 'usr' AND password = 'pwd'");
    conn.commit();
  }
} else {
  // Usr/Pwd wrong
}
conn.rollback();

Что произойдет, если пользователь войдет в систему между операторами выбора и обновления на другом сервере?происходит ли сбой фиксации, поскольку таблица была изменена кем-то другим во время транзакции, или она все же выполняется?

Должен ли я лучше использовать подход, подобный

UPDATE users SET server = 123 WHERE user = 'usr' AND pwd = 'pwd' AND server IS NULL

, и проверить, были ли 0 строкзатронуты?Если это так, я должен проверить, существует ли пользователь в запросе.

Проблемы с Simmilar возникают при регистрации нового пользователя с помощью INSERT.Должен ли я использовать транзакционный подход или объявить пользовательский столбец как UNIQUE и перехватить исключения SQL?

Ответы [ 2 ]

2 голосов
/ 25 февраля 2011

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

Вы также должны думать о количестве:

  • Никогда, никогда, никогда не храните пароли в виде простого текста в базе данных. Вам нужно использовать односторонний хеш. Также обязательно обратите внимание на алгоритм хеширования и его реализацию. Ищите «HBGary» и «Anonymous», чтобы узнать, что может произойти, если вы этого не сделаете.
  • Подумайте о том, что произойдет, если пользователь войдет в систему на одном сервере, и у клиента произойдет сбой, прежде чем он сможет выйти из системы.
0 голосов
/ 25 февраля 2011

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

...