我有一个servlet过滤器来强制用户身份验证。它检查HttpSession中是否存在非空对象。由于某种原因,我无法弄清楚,会话包含一个具有正确名称的对象,但HttpSession.getAttribute返回为null。这是它经历的过程。
从登录页面调用包含以下用户验证代码的操作。此时,我100%确定对象“login”不为空。
if (passWordIsValid) {
HttpSession session = getCurrentFacesSession();
session.setAttribute("loginBean", login);
return "welcome";
} else {
// error handling here
}
结果“欢迎”进入小面板页面,其中包含以下代码:
<h:outputText value="Welcome #{sessionScope.loginBean.email}"/>
此代码确实成功显示了电子邮件地址,从而确认会话范围中存在loginBean对象,并且它不为null。该欢迎页面上的命令链接将请求提交给其他视图。当servlet过滤器拦截请求时,它会执行以下操作:
HttpSession session = ((HttpServletRequest) servletRequest).getSession();
Object beanObj = session.getAttribute("loginBean");
if (beanObj!=null) {
chain.doFilter(servletRequest,servletResponse);
} else {
// code to send back to login page
}
它总是将用户发送回登录页面,因为beanObj总是返回null。这是一个我似乎无法解决的谜。有什么建议?
EDITED 为了进一步调试,我将日志代码添加到servlet过滤器中以转储会话中的属性:
for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements();) {
log("Found Session attribute="+e.nextElement());
}
输出确认会话中有一个名为“loginBean”的属性!这令人抓狂......
已编辑
如果是不可见的字符,我完全重新输入了bean的名称,然后进行了完整的清理/重新发布以确保我获得了最新的代码。
HttpSession session = ((HttpServletRequest) servletRequest).getSession();
String s = "loginBean";
Object beanObj = session.getAttribute(s);
if (beanObj!=null) {
chain.doFilter(servletRequest,servletResponse);
} else {
// code to send back to login page
}
同样的行为......
调试
我注册了一个HttpSessionAttributeListener。输出确认bean已添加到会话中。该bean没有后续实例被替换或从会话中删除。我不确定如何继续使用调试器,尤其是在像这样复杂的事情上(在JVM中运行的整个Web容器。)
答案 0 :(得分:0)
好的,我现在感到愚蠢。这是servlet过滤器代码中的一个错误;实际上是两个第一个是在一个doFilter(请求,响应)方法调用之后我错过了一个'return'语句。第二个是JSESSIONID被附加到URL,我没有在始终允许登录页面的代码中考虑到这一点。好吧,实际上我试图解释它,但我做错了。我写过它,好像JSESSIONID是一个查询参数,像这样?JSESSIONID = blah,实际上它不是一个查询参数,它使用这样的分号:; JSESSIONID = blah。
这些错误的组合使得看起来servlet过滤器无法在会话中找到对象;但实际发生的事情是日志消息来自PREVIOUS请求 - 当bean实际存在时,它从未在后续请求中检查会话。哎呦!对于那些将来遇到这个问题的人,我会告诉你我是如何理解的:我从servlet过滤器中删除了所有代码,这些代码进行了转发或重定向,并在底部放置了一个doFilter(),然后放入了日志语句看到价值。然后立即明白发生了什么。 HttpSessionAttributeListener也很有用。