Как отфильтровать неавторизованных пользователей и показать форму входа без запуска сеанса?
Моя ситуация такова:
У меня есть сервлет, который не должен быть доступен неавторизованным пользователям. Этот сервлет выполняет некоторую бизнес-логику и передает некоторые промежуточные данные в jsp
secret.jsp
с помощьюRequestDispatcher::forward()
, (secret.jsp
это просто пример, будет много сервлетов и / или jsps).Также есть логин jsp
login.jsp
,Перед сервлетом сидит фильтр, который следует перенаправить на
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);
Проблемы
Переадресация в сервлете заставляет фильтр срабатывать 2*2=4 раза (дважды, потому что он переходит вперед и назад при поступлении запроса и доставке ответа). Я хотел бы, чтобы он был запущен только один раз (когда поступает первоначальный запрос) - или, по крайней мере, только дважды.
Сессия началась. Я не хочу, чтобы сеанс запускался до тех пор, пока пользователь фактически не был успешно аутентифицирован (т.е. отправил куки-файл JSESSIONID клиенту).
Какой самый элегантный способ исправить эти проблемы?
Я бы не хотел перенаправлять, отправив браузеру 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>
1 ответ
Переадресация в сервлете заставляет фильтр срабатывать 2*2=4 раза (дважды, потому что он переходит вперед и назад при поступлении запроса и доставке ответа). Я хотел бы, чтобы он был запущен только один раз (когда поступает первоначальный запрос) - или, по крайней мере, только дважды.
Вы забыли вернуться после пересылки, в результате чего ваш фильтр продолжил цепочку запросов / ответов.
rd.forward(request, response);
return;
Вызов произвольного метода Java, безусловно, не приведет к внезапному завершению текущего блока метода и выпадению из него (ожидайте System#exit()
или когда это исключение, конечно, но это отдельная история).
Сессия началась. Я не хочу, чтобы сеанс запускался до тех пор, пока пользователь фактически не был успешно аутентифицирован (т.е. отправил куки-файл JSESSIONID клиенту).
Это вызвано не фильтром, а скорее всего вашим JSP. Добавьте следующее в начало JSP, чтобы явно отключить неявное создание сеанса с помощью JSP:
<%@page session="false" %>
При необходимости создайте HttpSessionListener
и поставить точку останова на sessionCreated()
метод, чтобы зафиксировать истинную причину.