我一直在使用从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建议的那样,但至少直接的问题已经解决了。