私は JavaEE 7 で遊んでいて、単純なログイン メカニズムで webapp を作成しようとしました。
User
ユーザーに関するデータを保持するという JPA で永続化される EJB エンティティ クラスがあります。WAR では、呼び出されたセッション スコープのマネージド BeanUserManagedBean
が現在のユーザーの追跡を担当するため、User
誰かが正常にログインしたときに設定されるタイプのプロパティがあります。フィルタはこのプロパティの値を監視しており、必要に応じてログイン ページにリダイレクトします。もちろん、 と の両方User
がUserManagedBean
シリアライズ可能です (インターフェイスを実装し、シリアライズ不可能なものは含まれません)。
私の問題は、ログインが成功した後、ページを更新するとログインページに戻り、以前に設定しuser
たプロパティが null になっていることです (実際、これがフィルターがリダイレクトをトリガーする理由です)。
これが私が試したものです:
- 分離されたロジックとデータ: UserManagedBean には、この 1 つのプロパティといくつかのヘルパー メソッドしかありません。EJB はなく、Java マジックに関連するものは何もありません。
javax.faces.STATE_SAVING_METHOD
web.xml のコンテキスト パラメータをサーバーとクライアントの両方に設定しようとしましたが、何も変わりませんでした。- セッション スコープのマネージド Bean が同じままであることを確認しました。そのうちの 1 つだけが作成されますが、ログイン ページから移動した後、何らかの理由で user の値が null になります。
- NetBeans デバッガによると、
user
フィールドは、ログインしているユーザーに設定する以外はアクセスされません。 - カスタムのシリアル化メソッドを指定すると、実験中に UserManagedBean がシリアル化または逆シリアル化されないことが明らかになりました。
user
Chrome でのデバッグは、セッション ID が Cookie に保存され、値が失われたときに変更されないことを示唆しています。- 例外は検出されません。
何か些細なことを見逃しているに違いありません。
(更新:それは確かに些細なことであり、 JSF やマネージド Bean とは関係ありません。以下の私の回答を参照してください。)
私のコードは次のとおりです。
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...
//...
}