Сервлет Java - другой идентификатор JSESSION, когда сервлет защищен. Почему?

Я удалил свой прецедентный пост, чтобы воссоздать более четкое. Для информации я упростил код, чтобы сделать его проще.

Представляю вам свою проблему.

Мой сервлет HelloWorld:

public class HelloWorld extends HttpServlet {

    private String message;

    public void init() throws ServletException {
        // Do required initialization
        message = "Hello World";
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Set response content type
        response.setContentType("text/html");

        // session test
        System.out.println( request.getSession().getId() );

        PrintWriter out = response.getWriter();
        out.println("<html><head><script src='./dwr/engine.js'></script><script src='./dwr/util.js'></script></head><body><h1>Hello World</h1></body></html>");
    }

    public void destroy() {
        // do nothing.
    }
}

Сервлет отображает html-страницу с сообщением HellWorld и включает файлы javascript DWR (Direct Web Remoting). Файлы javascript DWR извлекаются из сервлета /dwr/.

Web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <display-name>TestDWR2</display-name>

    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>test.HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld/*</url-pattern>
    </servlet-mapping>

    <servlet>
      <servlet-name>dwr-invoker</servlet-name>
      <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>WEB-INF/dwr.xml</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
      <servlet-name>dwr-invoker</servlet-name>
      <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Extranet resource</web-resource-name>
            <description>Extranet resources</description>
            <url-pattern>/HelloWorld/*</url-pattern>
            <url-pattern>/dwr/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>intranet_admin</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Extranet</realm-name>
    </login-config>

    <security-role>
        <description>Intranet Admin</description>
        <role-name>intranet_admin</role-name>
    </security-role>

</web-app>

Сервлеты /HelloWorld и /dwr защищены. Логин основан на базе данных пользователей tomcat:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
     <user username="tomcat" password="tomcat" roles="intranet_admin"/>
</tomcat-users>

HTTP-запрос/ответ:

Для вызова сервлета HelloWorld

введите здесь описание изображения

Для вызова сервлета DWR (engine.js)

введите здесь описание изображения

Для вызова сервлета DWR (util.js)

введите здесь описание изображения

Для вызова сервлета DWR (_System.pageLoaded.dwr)

введите здесь описание изображения

Как видите, JSESSIONID меняется для каждого запроса, и это моя проблема, которую я не могу решить в течение некоторого времени...

Я все еще прогрессирую последние несколько дней. Теперь я знаю, что проблема возникает только тогда, когда сервлеты защищены:

    <web-resource-collection>
        <web-resource-name>Extranet resource</web-resource-name>
        <description>Extranet resources</description>
        <url-pattern>/HelloWorld/*</url-pattern>
        <url-pattern>/dwr/*</url-pattern>
    </web-resource-collection>

Если удалить эту безопасность, каждый запрос возвращает один и тот же JSESSIONID. Почему? Я сказал, что это не связано с DWR. Когда я вызываю сервлет для возврата другого JS, такого как jQuery, я сталкиваюсь с той же проблемой.

Можешь мне помочь?

Вы можете найти по этой ссылке войну для развертывания на tomcat (Tomcat 7), чтобы обнаружить проблему:

https://www.wetransfer.com/downloads/dd1729b56d26e94b9d9a5dcb264dce0c20141105104229/a623a93ec2bcbb8b3ac8e2695cbe646c20141105104229/b4bc1e

Вы можете найти по этой ссылке источник кода:

https://www.wetransfer.com/downloads/fd8a74c850a5beb32d6529576f15f42c20141105104405/6f89adba0c853d48e392edb1d3ca562620141105104405/f67f43

Большое Вам спасибо.


person Franck S    schedule 05.11.2014    source источник
comment
Думаю, это связано с защитой от фиксации сессии. Обычно вы генерируете новый идентификатор сеанса каждый раз, когда выполняете аутентификацию, чтобы убедиться, что ни у кого другого нет старого (незащищенного) идентификатора сеанса, и он внезапно входит в систему. Кажется, что базовая аутентификация регистрирует каждый запрос и, следовательно, изменяет идентификатор сеанса. Возможно, где-то отсутствует обработчик сеанса, который пропускает BA, если сеанс все еще действителен, но я не уверен в дефолтах. Что это за кот и есть ли у него глобальные изменения клапанов и фильтров? Какой мир вы используете?   -  person eckes    schedule 05.11.2014
comment
Если я установлю changeSessionIdOnAuthentication=false в Context.xml, это сработает, но я хочу сохранить эту безопасность, если это возможно. У вас есть другое решение для сохранения безопасности? Фильтр сервлетов? Обработчик сеанса? Я использую tomcat 7. Я использую область org.apache.catalina.realm.UserDatabaseRealm. Спасибо за помощь   -  person Franck S    schedule 05.11.2014
comment
Я думаю, должен быть способ настроить tomcat для пропуска (повторной) аутентификации, если сеанс присутствует/действителен. Однако я понятия не имею, как :)   -  person eckes    schedule 05.11.2014


Ответы (2)


Я не проверял войны, но это может быть проблема фиксации сеанса, которая включена по умолчанию в Tomcat 7. Он в основном изменяет идентификатор сеанса, когда он проходит аутентификацию. Проверьте больше и попробуйте отключить, просто чтобы убедиться, что это ваша проблема http://java.dzone.com/tips/turning-session-fixation

person Master Slave    schedule 05.11.2014
comment
Действительно, если я установлю changeSessionIdOnAuthentication=false в Context.xml, это сработает. Спасибо. Есть ли другое решение, не ставящее под угрозу безопасность? Фильтр сервлетов или что-то другое? Я отвечаю на свой вопрос, чтобы добавить захват HTTP-запроса/ответа - person Franck S; 05.11.2014

Действительно, если я установлю changeSessionIdOnAuthentication="false" в Context.xml, это сработает:

<Context path="/test" reloadable="true" docBase="D:\projects\test2\TestDWR" workDir="D:\projects\test2\TestDWR\work" >
<Valve className="org.apache.catalina.authenticator.BasicAuthenticator"
  changeSessionIdOnAuthentication="false" />
</Context>

Но я вижу, что http-запрос делается 2 раза:

введите здесь описание изображения

Есть ли другое решение, не ставящее под угрозу безопасность? Фильтр сервлетов или что-то другое?

Это действительно блокирует, потому что в первый раз извлекает данные из базы данных и устанавливает их в сеансе. И во втором запросе из-за изменения jsessionid данные больше не находятся в сеансе и должны быть снова получены...

Спасибо за помощь

person Franck S    schedule 05.11.2014
comment
Это нормально, что браузер пытается без BA, когда он получает 401, он повторяет попытку с заголовком авторизации. Я не уверен, почему браузер делает это для дочерних ресурсов, но да ладно.. :) - person eckes; 05.11.2014