Я использую JSF 1.2 с Richfaces и Facelets.
У меня есть приложение со многими ограниченными по объему сессией бобами и некоторыми компонентами приложения.
Пользователь входит в систему с, скажем, Firefox. Сессия создается с идентификатором = "A"; Затем он открывает Chrome и входит в систему снова с теми же учетными данными. Сессия создается с идентификатором = "B".
Когда сессия "B" создается, я хочу смочь уничтожить сессию "A". Как сделать это?
Также. когда пользователь в Firefox делает что-либо, я хочу смочь отобразить всплывающее окно или некоторое уведомление, говоря, что "Вы вышлись из системы, потому что Вы вошли в систему от где-то в другом месте".
У меня есть sessionListener, кто отслеживает сессии, созданные и уничтоженные. Вещь, я мог сохранить объект HTTPSession в ограниченном по объему приложением бобе и уничтожить его, когда я обнаруживаю, что пользователь вошел в систему дважды. Но что-то мне подсказывает, что является просто неправильным и не будет работать.
JSF отслеживает сессии где-нибудь на стороне сервера? Как получить доступ к ним идентификатором? В противном случае, как выгнать первое, входят в систему пользователя, когда он входит в систему дважды?
Независимый от БД подход заключался бы в том, чтобы позволить пользователю
иметь статическую переменную Map
и реализовать HttpSessionBindingListener
(и Object # equals ()
и Object # hashCode ()
). Таким образом, ваше веб-приложение по-прежнему будет работать после непредвиденного сбоя, который может привести к тому, что значения БД не будут обновлены (вы, конечно, можете создать ServletContextListener
, который сбрасывает БД при запуске веб-приложения, но это только больше и больше работы).
Вот как должен выглядеть пользователь
:
public class User implements HttpSessionBindingListener {
// All logins.
private static Map<User, HttpSession> logins = new ConcurrentHashMap<>();
// Normal properties.
private Long id;
private String username;
// Etc.. Of course with public getters+setters.
@Override
public boolean equals(Object other) {
return (other instanceof User) && (id != null) ? id.equals(((User) other).id) : (other == this);
}
@Override
public int hashCode() {
return (id != null) ? (this.getClass().hashCode() + id.hashCode()) : super.hashCode();
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = logins.remove(this);
if (session != null) {
session.invalidate();
}
logins.put(this, event.getSession());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
logins.remove(this);
}
}
Когда вы входите в систему пользователя
следующим образом:
User user = userDAO.find(username, password);
if (user != null) {
sessionMap.put("user", user);
} else {
// Show error.
}
, тогда он вызывает valueBound ()
, который удалит всех ранее вошедших в систему пользователей из карты логинов
и аннулирует сеанс.
Когда вы выходите из системы пользователя
следующим образом:
sessionMap.remove("user");
или когда время ожидания сеанса истекло, то будет вызвана функция valueUnbound ()
, которая удалит пользователя из логины
карта.
userLoggedInCount
аннулируем()
сессию и уменьшаем значение в базе данных