Я играю с JavaEE 7 и пытался написать веб-приложение с простым механизмом входа в систему.
Существует класс сущности EJB с JPA, который называется User
, содержащий данные о пользователях. В WAR управляемый bean-компонент с областью сеанса с именем UserManagedBean
отвечает за отслеживание текущего пользователя, поэтому он имеет свойство типа User
, которое устанавливается, когда кто-то успешно входит в систему. Фильтр отслеживает значение этого свойства и при необходимости перенаправляет на страницу входа. Конечно, и User
, и UserManagedBean
сериализуемы (реализуют интерфейс и не содержат ничего несериализуемого).
Моя проблема в том, что после успешного входа в систему обновление страницы возвращает меня на страницу входа, И мое ранее установленное свойство user
теперь имеет значение NULL (на самом деле, именно поэтому фильтр запускает перенаправление).
Вот что я пробовал:
- Разделение логики и данных: UserManagedBean теперь имеет только одно свойство и несколько вспомогательных методов, никаких EJB-компонентов и ничего, связанного с магией Java.
- Пытался установить параметр контекста
javax.faces.STATE_SAVING_METHOD
в web.xml как для сервера, так и для клиента, ничего не изменилось. - Проверено, что управляемый bean-компонент с привязкой к сеансу остается прежним: создается только один из них, но каким-то образом значение user обнуляется после перехода со страницы входа.
- Согласно отладчику NetBeans, к полю
user
не осуществляется доступ, за исключением того, что оно устанавливается для вошедшего в систему пользователя. - Указание пользовательских методов сериализации показало, что UserManagedBean не сериализуется и не десериализуется во время эксперимента.
- Отладка в Chrome предполагает, что идентификатор сеанса сохраняется в файле cookie и не изменяется при потере значения
user
. - Никаких исключений не обнаружено.
Должно быть, мне не хватает чего-то тривиального, любая помощь будет оценена по достоинству.
(ОБНОВЛЕНИЕ: Это действительно было тривиально и не относилось к JSF или управляемым компонентам, см. мой ответ ниже.)
Мой код следующий:
User
класс:
@Entity(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String username;
private boolean administrator;
private byte[] salt;
private byte[] passwordHash;
public String getUsername() {
return username;
}
public void setUsername(String userName) {
this.username = userName;
}
public boolean isAdministrator() {
return administrator;
}
public void setAdministrator(boolean administrator) {
this.administrator = administrator;
}
public byte[] getSalt() {
return salt;
}
public void setSalt(byte[] salt) {
this.salt = salt;
}
public byte[] getPasswordHash() {
return passwordHash;
}
public void setPasswordHash(byte[] passwordHash) {
this.passwordHash = passwordHash;
}
@Override
public int hashCode() {
int hash = 0;
hash += (username != null ? username.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.username == null && other.username != null) || (this.username != null && !this.username.equals(other.username))) {
return false;
}
return true;
}
@Override
public String toString() {
return "hu.bme.aut.mv.testbay.ejb.entities.User[ id=" + username + " ]";
}
}
UserManagedBean
класс:
@ManagedBean(name = "userManagedBean")
@SessionScoped
public class UserManagedBean implements Serializable {
private static final long serialVersionUID = 1L;
private User currentUser;
public User getCurrentUser() {
return currentUser;
}
public void setCurrentUser(User user) {
this.currentUser = user;
}
public boolean isLoggedIn() {
return currentUser != null;
}
public boolean isAdmin() {
return currentUser != null && currentUser.isAdministrator();
}
public String logout() {
currentUser = null;
return "/faces/index.xhtml";
}
/**
* Creates a new instance of UserManagedBean
*/
public UserManagedBean() {
System.out.println("UserManagedBean constructed!");
}
}
Фильтр (doBeforeProcessing
):
HttpSession session = ((HttpServletRequest) request).getSession(false);
UserManagedBean userManagedBean = (session != null) ? (UserManagedBean) session.getAttribute("userManagedBean") : null;
if (userManagedBean == null || userManagedBean.getCurrentUser() == null) {
((HttpServletResponse)response).sendRedirect(((HttpServletRequest) request).getContextPath() + "/faces/login.xhtml");
}
ОБНОВЛЕНИЕ:
Важно отметить, что пользователь правильно настроен один раз, и переход к экрану приветствия происходит должным образом. Однако запрос nex обнаруживает, что свойство пользователя пусто.
Код, запускающий аутентификацию, находится в классе LoginManagedBean
с областью действия запроса:
@ManagedBean
@RequestScoped
public class LoginManagedBean implements Serializable {
@EJB
private AuthenticationSessionBeanLocal authBean;
@ManagedProperty("#{userManagedBean}")
private UserManagedBean userManagedBean;
@PostConstruct
public void Dummy() {
User user = userManagedBean.getCurrentUser();
}
public UserManagedBean getUserManagedBean() {
return userManagedBean;
}
public void setUserManagedBean(UserManagedBean userManagedBean) {
this.userManagedBean = userManagedBean;
}
private String username;
private String password;
//Some getters and setters...
//...
public String login() throws NoSuchAlgorithmException {
if (authenticate(username, password)) {
if (userManagedBean.getCurrentUser().isAdministrator())
return "/faces/admin/welcome.xhtml?faces-redirect=true";
else
return "/faces/testing/welcome.xhtml?faces-redirect=true";
}
return null;
}
private boolean authenticate(String username, String password) throws NoSuchAlgorithmException {
userManagedBean.setCurrentUser(authBean.authenticate(username, password));
if (userManagedBean.getCurrentUser() == null)
return false;
return true;
}
//Constructor and methods...
//...
}
session.getAttribute("userManagedBean")
. Где вы установили атрибут перед тем, как получить его? - person Mr.J4mes   schedule 13.05.2014