0

我有一个Stateful Session Bean保存我的登录会话的 aJSF Session Bean和一个Servlet Filter.

我需要做的是阻止非登录用户访问我的页面,所以我做了一个过滤器。

doFilter()是这样的:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    String path = req.getRequestURI().substring(req.getContextPath().length());
    System.out.println(userManager.isLogged());
    if (userManager.isLogged() || path.equals("/") || path.equals("/index.xhtml") || path.startsWith(ResourceHandler.RESOURCE_IDENTIFIER) || path.startsWith("/resources/") || path.startsWith("/admin") || path.equals("/admin/login.xhtml")) {
        chain.doFilter(request, response);
    } else {
        request.getRequestDispatcher("/error.xhtml").forward(request, response);
    }
}

在哪里userManager找到:

private UserManagerLocal lookupUserManagerLocal() {
    try {
        Context c = new InitialContext();
        return (UserManagerLocal) c.lookup("java:global/UNILIFE/UNILIFE-ejb/UserManager!ejb.UserManagerLocal");
    } catch (NamingException ne) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
        throw new RuntimeException(ne);
    }
}

现在,总是System.out.println(userManager.isLogged());打印为假,而打印为真。#{loginBean.logged}

请注意,这loginBean.logged只是

public boolean isLogged() {
    return userManager.isLogged();
}

并且,在我的托管 Bean 中,userManager通过

@EJB
private UserManagerLocal userManager;

似乎 servlet 不采用与 JSF 托管 Bean 相同的 SFSB。

我究竟做错了什么?

编辑:新代码

小服务程序

UserManagerLocal userManager = lookupUserManagerLocal();
private UserManagerLocal lookupUserManagerLocal() {
    try {
        Context c = new InitialContext();
        UserManagerLocal userM = (UserManagerLocal) c.lookup("java:global/UNILIFE/UNILIFE-ejb/UserManager!ejb.UserManagerLocal");
        HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
        req.setAttribute("userManager", userM);
        return userM;
    } catch (NamingException ne) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
        throw new RuntimeException(ne);
    }
}

jsf豆

@PostConstruct
public void init(){
    HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
    userManager = (UserManagerLocal) req.getSession().getAttribute("userManager");
}
4

2 回答 2

1

每次查找有状态会话 bean 时,都会创建一个唯一实例,因此 isLogged 可能会返回默认字段值。您需要以某种方式将有状态会话 bean 实例存储在 HttpSession 中并从您的过滤器中检索它。我缺乏 JSF 专业知识,所以我不知道是否有方便的方法来共享有状态会话 bean 实例,或者您是否需要手动将 JSF bean 链接到有状态 bean。

于 2012-05-24T17:52:52.960 回答
0

每个 JNDI 查找都会返回一个新的 bean 句柄。因此,您在调用方法时获得默认值,丢弃以前的活动。如其他帖子中所述,您需要保存该引用(HttpSession)以对其进行进一步操作。

下面是在 JSF bean 中访问会话的示例代码。

HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();

根据请求,您可以获得会话然后放入其中。

session.setAttribute("userManager", userManager);

现在在过滤器中,您可以从请求中检索 bean。此外,相应地修改代码。

于 2012-05-24T18:19:26.493 回答