我的情况是:
我有一个servlet,未经过身份验证的用户无法访问。此servlet执行一些业务逻辑,并通过secret.jsp
将一些中间数据传递给jsp RequestDispatcher::forward()
。 (secret.jsp
只是一个例子,会有很多servlet和/或jsps)。
还有一个登录jsp login.jsp
。
在servlet前面有一个过滤器,它应该重定向到login.jsp
来自未经验证的用户的所有请求。基本上doFilter()
看起来像:
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if(-1 == req.getRequestURI().indexOf("login.jsp")) {//if page which is not whitelisted
HttpSession session = req.getSession(false);
if(null == session) {
RequestDispatcher rd = req.getServletContext().getRequestDispatcher("/login.jsp");
rd.forward(request, response);
}
else {
//not whitelisted but already logged in...
log("we are logged in");
}
}
chain.doFilter(request, response);
问题是
servlet中的转发使得过滤器被触发2 * 2 = 4次(两次,因为它来回传递,因为请求进入,并且响应被传递)。我希望它只被触发一次(当初始请求进入时) - 或者至少只触发两次。
会话已启动。我不希望在用户实际上未成功通过身份验证之前启动会话(即将JSESSIONID cookie发送到客户端)。
解决这些问题最优雅的方法是什么?
我不想通过向浏览器发送Location
标头来重定向,而是在内部进行重定向。
附录
secret.jsp
:
<%@page contentType="text/html" pageEncoding="UTF-8" import="java.util.*"%>
<%@taglib prefix="tags" uri="/WEB-INF/tlds/tag_library.tld" %>
<tags:wrapper title="hello world">
hello ${requestScope.msg}
</tags:wrapper>
使用标签
wrapper.tagf
:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@tag pageEncoding="UTF-8"%>
<%@attribute name="title" required="true" type="java.lang.String" %>
<%@attribute name="menu" type="java.util.HashMap<String, Object>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="css/reset.css"/>
<link rel="stylesheet/less" type="text/css" href="css/default.less"/>
<script src="js/less-1.1.5.min.js" type="text/javascript"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${pageScope.title}</title>
</head>
<body>
<div id="leftMenu">menu</div>
<div id="body">
<jsp:doBody/>
</div>
</body>
</html>
答案 0 :(得分:0)
servlet中的转发使得过滤器被触发2 * 2 = 4次(两次,因为它来回传递,因为请求进入,并且响应被传递)。我希望它只被触发一次(当初始请求进入时) - 或者至少只触发两次。
您忘记了在前进后返回,这导致您的过滤器仍然继续请求/响应链。
rd.forward(request, response);
return;
调用任意Java方法肯定不会突然终止当前正在运行的方法块并跳出它(期望System#exit()
或当它抛出异常当然,但这是一个故事)< / em>的
会话已启动。我不希望在用户实际上没有成功通过身份验证之前启动会话(即将JSESSIONID cookie发送到客户端)。
这是在过滤器之外的其他地方引起的,很可能是由JSP引起的。将以下内容添加到JSP的顶部以显式禁用JSP的隐式会话创建:
<%@page session="false" %>
如有必要,创建一个HttpSessionListener
并在sessionCreated()
方法上设置一个断点,以实现真正的根本原因。