Как отфильтровать неавторизованных пользователей и показать форму входа без запуска сеанса? - PullRequest
0 голосов
/ 07 декабря 2011

Моя ситуация такова:

  1. У меня есть сервлет, который не должен быть доступен неавторизованным пользователям.Этот сервлет выполняет некоторую бизнес-логику и передает некоторые промежуточные данные в jsp secret.jsp через RequestDispatcher::forward().(secret.jsp это просто пример, будет много сервлетов и / или jsps).

  2. Также есть логин jsp login.jsp.

  3. Перед сервлетом расположен фильтр, который должен перенаправлять на 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);
    

Проблемы:

  1. Перемещение в сервлете вызывает срабатывание фильтра 2 * 2= 4 раза (дважды, потому что он идет туда-сюда, когда поступает запрос и как доставляется ответ).Я хотел бы, чтобы он запускался только один раз (когда поступает первоначальный запрос) - или, по крайней мере, только дважды.

  2. Сеанс запущен.Я не хочу, чтобы сеанс начинался до тех пор, пока пользователь фактически не был успешно аутентифицирован (т.е. отправил cookie 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 Ответ

0 голосов
/ 07 декабря 2011

Переадресация в сервлете вызывает срабатывание фильтра 2 * 2 = 4 раза (дважды, потому что он перемещается назад и вперед при поступлении запроса и получении ответа). Я хотел бы, чтобы он срабатывал только один раз (когда поступает первоначальный запрос) - или, по крайней мере, только дважды.

Вы забыли вернуться после пересылки, в результате чего ваш фильтр продолжил цепочку запросов / ответов.

rd.forward(request, response);
return;

Вызов произвольного метода Java, безусловно, не приведет к внезапному завершению текущего запущенного блока метода и выпадению из него (ожидайте System#exit() или когда он, конечно, вызывает исключение, но это отдельная история) .


Сессия начата. Я не хочу, чтобы сеанс начинался до тех пор, пока пользователь фактически не был успешно аутентифицирован (т.е. отправил cookie JSESSIONID клиенту).

Это вызвано не фильтром, а скорее всего вашим JSP. Добавьте следующее в начало JSP, чтобы явно отключить неявное создание сеанса с помощью JSP:

<%@page session="false" %>

При необходимости создайте HttpSessionListener и установите точку останова для метода sessionCreated(), чтобы определить истинную причину.

...