Webfilter只管理登录用户在第二个响应(记住我)



我一直在使用从balusC的答案中获得灵感的代码。基本上,它是一个网络过滤器,如果有一个记住我的cookie,它会尝试登录用户。

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

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

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

我试图在登录发生后的一些不同的地方重定向,但当我尝试的页面布局中断…

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

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);
}

从我所看到的,您实际上并没有在第一次运行时登录用户。到目前为止,您所做的只是在创建的会话中设置一个值,而容器实际上没有对用户进行身份验证。

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);
        }
    }

我做了一个快速修复来解决这个问题。我没有将用户实体存储在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构造完成。然后sessionscope - 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管理的身份验证,或者像Kollossus建议的那样,但至少直接的问题已经解决了。

相关内容

  • 没有找到相关文章

最新更新