0

我一直在玩从 balusC 的答案之一启发的代码。基本上它是一个网络过滤器,如果有一个记住我的 cookie,它会尝试登录用户。

登录发生后,它首先从 userService-EJB 获取 MyUser 实体并将其放置在作为 @SessionScoped jsf-ManagedBean 的 MUserSessionBean 中

问题是在第一个响应中,用户显示为未登录。

但是在日志中我可以看到它正在登录,如果我只是在浏览器中请求页面刷新,响应将显示登录用户。

登录发生后,我尝试在不同的地方放置重定向,但是当我尝试这样做时页面布局中断..

如何在第一响应中成功显示登录用户?

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
        ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    MUserSessionBean mUserSessionBean = (MUserSessionBean) request.getSession(true)
            .getAttribute("mUserSessionBean");

    if (mUserSessionBean != null && mUserSessionBean.getCurrentUser() == null) {

        String uuid = CookieUtil.getCookieValue(request, CookieUtil.COOKIE_NAME);

        if (uuid != null) {
            MyUser user = userService.findUserByUUID(uuid);

            if (user != null) {
                mUserSessionBean.setCurrentUser(user);
                CookieUtil.addCookie(response, CookieUtil.COOKIE_NAME, uuid, CookieUtil.COOKIE_AGE); 
            } else {
                CookieUtil.removeCookie(response, CookieUtil.COOKIE_NAME);
            }
        }
    }

    // pass the request along the filter chain
    chain.doFilter(req, res);
}
4

2 回答 2

1

从我所见,您实际上并没有在第一次访问时登录用户。到目前为止,您所做的只是在没有容器实际验证用户身份的情况下在创建的会话中设置一个值。

remember-me 功能要求您使用您使用 remember-me 令牌提取的凭据代表用户对领域进行身份验证。你没有这样做。即使在用户已登录的页面刷新时,从技术上讲,这也是不正确的。它只显示为已登录,因为

     if (mUserSessionBean != null && mUserSessionBean.getCurrentUser() == null) 

true在第一次请求页面后解析并跳过所有检查。后续请求只是因为您MyUser在会话中强行放置了一个实例而通过。实际上,用户没有登录,这可能是导致应用程序中其他地方出现分页符的原因。

您需要针对领域对用户进行真正的身份验证才能和平统治:)

    if (uuid != null) {
        MyUser user = userService.findUserByUUID(uuid);

        if (user != null) {
            request.login(user.username,user.password); //Authenticate!!!!
            mUserSessionBean.setCurrentUser(user);
            CookieUtil.addCookie(response, CookieUtil.COOKIE_NAME, uuid, CookieUtil.COOKIE_AGE); 
        } else {
            CookieUtil.removeCookie(response, CookieUtil.COOKIE_NAME);
        }
    }
于 2013-03-06T03:37:15.593 回答
0

我做了一个快速修复,解决了这个问题。我没有将用户实体存储在 SessionScoped ManagedBean 中,而是将其直接存储在会话中。所以过滤方法看起来像这样:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
        ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    MyUser user = (MyUser) request.getSession(true).getAttribute("user");

    if (user == null) {

        String uuid = CookieUtil.getCookieValue(request, CookieUtil.COOKIE_NAME);

        if (uuid != null) {
            user = ub.findUserByUUID(uuid);

            if (user != null) {
                request.getSession().setAttribute("user", user);
                CookieUtil.addCookie(response, CookieUtil.COOKIE_NAME, uuid, CookieUtil.COOKIE_AGE);
            } else {
                CookieUtil.removeCookie(response, CookieUtil.COOKIE_NAME);
            }
        }
    }

    // pass the request along the filter chain
    chain.doFilter(req, res);
}

优点是过滤器不必等待 ManagedBean 被构造。然后 SessionScoped-Bean 进入会话并获取过滤器可能放置在那里的实体。

@ManagedBean
@SessionScoped
public class MUserSessionBean {

    private MyUser currentUser;

    @PostConstruct
    public void init() {
        if (currentUser == null) {
            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();

            currentUser = (MyUser) context.getSessionMap().get("user");
        }
    }
...
}

我将研究 servlet-managed-authentication 或它可能被称为 Kolllossus sugested 的东西,但至少眼前的问题已经消失了。

于 2013-03-06T17:55:40.883 回答