Просмотр, объявленный в ‹protected-views›, все еще доступен после манипулирования токеном CSRF

Я изучаю новые функции в JSF 2.2 (пока довольно круто), но я до сих пор не понимаю, как работают защищенные представления, я создал facelet1 со ссылкой на facelet2, например:

<h:link styleClass="link" value="Go to protected page" id="link1"
    outcome="/protected/facelet2.xhtml"></h:link>

и в моем faces-config.xml я добавил это:

<protected-views>
    <url-pattern>/protected/facelet2.xhtml</url-pattern>
</protected-views>

Теперь, когда я запускаю страницу, в URL-адрес добавляется токен:

http://localhost:8080/<project>/protected/facelet2.faces?javax.faces.Token=1426608965211

Согласно документации, если токен не совпадает с токеном на сервере, запрос GET не обрабатывается (правильно ли я понимаю?).

Но если я изменю токен (с помощью Firebug или инструментов разработчика, включенных в браузер), запрос все равно будет обработан, даже если токен был изменен.

Я делаю что-то неправильно?


person CIOC    schedule 17.03.2015    source источник


Ответы (1)


Это вызвано тем, что ваш FacesServlet явно сопоставлен с шаблоном URL-адреса в стиле JSF 1.0 *.faces вместо шаблона URL-адреса в стиле JSF 2.0 *.xhtml. <protected-views><url-pattern> должен соответствовать фактическому шаблону URL, который вы видите в адресной строке браузера.

Итак, учитывая фактический URL-адрес /protected/facelet2.faces, вам необходимо настроить его, как показано ниже:

<protected-views>
    <url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>

Однако при этом я обнаружил некоторые неприятные проблемы в текущей реализации Mojarra 2.2.10:

  1. Фактически он не выполняет совпадение префикса / суффикса согласно спецификации сервлета 12.1 (в исходном коде есть даже расплывчатый комментарий, указывающий на это!). Это просто точное совпадение. Это означает, что вы не можете использовать шаблоны URL с подстановочными знаками, такие как /protected/*.

  2. При создании <h:link> он сравнивает шаблон URL защищенного представления не с разрешенным URL, а с идентификатором представления JSF. И при проверке входящего запроса он сравнивает URL-адрес запроса не с идентификатором представления JSF (как при генерации ссылки), а с <url-pattern>. Таким образом, это никогда не совпадает, что полностью объясняет, почему вы могли просто получить к нему доступ без действующего токена.

По сути, вам нужна следующая конфигурация, если вам нужно сохранить шаблон URL-адреса в стиле JSF 1.0 *.faces.

<protected-views>
    <url-pattern>/protected/facelet2.xhtml</url-pattern>
    <url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>

Затем он правильно выбрасывает javax.faces.application.ProtectedViewException при доступе без действительного токена. Намного лучше просто отобразить FacesServlet явно на *.xhtml в web.xml.

<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

Таким образом, вам никогда не придется иметь дело с виртуальными URL-адресами.

Я сообщил об этом ребятам из Мохарры как issue 3837.

Смотрите также:

person BalusC    schedule 17.03.2015
comment
Я также заметил проблему с шаблонами URL-адресов, действительно довольно неприятную проблему. Спасибо за действительно исчерпывающий ответ! - person CIOC; 18.03.2015