3

私は JavaEE 7 で遊んでいて、単純なログイン メカニズムで webapp を作成しようとしました。

Userユーザーに関するデータを保持するという JPA で永続化される EJB エンティティ クラスがあります。WAR では、呼び出されたセッション スコープのマネージド BeanUserManagedBeanが現在のユーザーの追跡を担当するため、User誰かが正常にログインしたときに設定されるタイプのプロパティがあります。フィルタはこのプロパティの値を監視しており、必要に応じてログイン ページにリダイレクトします。もちろん、 と の両方UserUserManagedBeanシリアライズ可能です (インターフェイスを実装し、シリアライズ不可能なものは含まれません)。

私の問題は、ログインが成功した後、ページを更新するとログインページに戻り、以前に設定しuserたプロパティが null になっていることです (実際、これがフィルターがリダイレクトをトリガーする理由です)。

これが私が試したものです:

  • 分離されたロジックとデータ: UserManagedBean には、この 1 つのプロパティといくつかのヘルパー メソッドしかありません。EJB はなく、Java マジックに関連するものは何もありません。
  • javax.faces.STATE_SAVING_METHODweb.xml のコンテキスト パラメータをサーバーとクライアントの両方に設定しようとしましたが、何も変わりませんでした。
  • セッション スコープのマネージド Bean が同じままであることを確認しました。そのうちの 1 つだけが作成されますが、ログイン ページから移動した後、何らかの理由で user の値が null になります。
  • NetBeans デバッガによると、userフィールドは、ログインしているユーザーに設定する以外はアクセスされません。
  • カスタムのシリアル化メソッドを指定すると、実験中に UserManagedBean がシリアル化または逆シリアル化されないことが明らかになりました。
  • userChrome でのデバッグは、セッション 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...
    //...
}
4

2 に答える 2