Я получил приложение, использующее Primefaces 6.0 / JSF 2.2, в котором у меня есть следующий сценарий.
Пользователь входит в систему, взаимодействуя с bean-компонентом @SessionScoped в приложении, и перенаправляется на homepage.jsf.После этого пользователь переходит на страницу через пункт меню (mypage.jsf).
public void login() throws IOException {
//.... Authentication mechanism here
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
externalContext.redirect(new StringBuilder(externalContext.getRequestContextPath())
.append("/homepage.jsf").toString());
return;
}
На той же вкладке он выходит из приложения и автоматически перенаправляется на страницу входа.
public String logout() {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.invalidateSession();
return "/login/login.jsf?faces-redirect=true";
}
Примечание : в то время как реализация входа / выхода из системы находится в обработчике @SessionScoped, остальная часть приложения для его действий / перенаправлений - @ ViewScoped.
Пользователь снова входит в приложение и пытается перейти по тому же пункту меню p: на той же странице, в которой он находился (mypage.jsf)
<p:menuitem value="" url="/mypage.jsf?faces-redirect=true" />
. На этом этапе приложение просматривает javax.faces..application.ViewExpiredException: представление не может быть восстановлено.Это поведение описано в многочисленных публикациях в stackoverflow, одна из которых содержит подробную информацию об этом поведении после аннулирования сеанса ( javax.faces.application.ViewExpiredException: представление не может быть восстановлено )
Вещи, которые я пробовал: я знаю, что это не так уж важно, и что в JSF 2.2 по умолчанию установлено значение false, все еще дал ему попытку.
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
Установка количества просмотров вручнуюсессия.Обратите внимание, что только 1 или 2 пользователя работают с приложением, но задайте его на всякий случай.
<context-param>
<description></description>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>15</param-value>
</context-param>
<context-param>
<description></description>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>15</param-value>
</context-param>
Кроме того, я создал фильтр, чтобы избежать кэширования, как упомянуто здесь Запретить пользователю видеть ранеепосещенная защищенная страница после выхода из системы
@WebFilter(servletNames = { "facesServlet" })
public class LoginFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
chain.doFilter(request, response);
return;
}
}
Я уверен, что установка javax.faces.STATE_SAVING_METHOD на client может решить мою проблему, но эточто-то, чего я стараюсь избегать.
Кроме того, я создал обработчик исключений, чтобы обработать исключение Viewexpireexception и перенаправить пользователя на определенную страницу.Конечно, это просто для разрешения такой ситуации, а не для решения проблемы.
Обновление 1
Я попытался использовать commandLink с ajax, установленным в false, для перенаправления.на «mypage.jsf» на всякий случай, если это была проблема, но с точно таким же исключением
<h:commandLink action="/mypagejsf?faces-redirect=true" ajax="false" value="My Link" />
Обновление 2 После первого выхода из системы и анализа заголовков запросов изСтраница входа, я заметил следующее:
1) Идентификатор сессии в браузере совпадает с идентификатором на сервере
2) Атрибут Referer показывает следующий URL http: //.... / mypage.jsf ?face-redirect = true .Это страница, на которой я получаю исключение, когда пытаюсь получить к нему доступ.
Обновление 3 Я также заметил, что когда я пытаюсь получить доступ к mypage.jsf после второго входа (до возникновения исключения), мой клиент запрашивает (если я не ошибаюсь) стот же идентификатор сеанса, который существует и на сервере.Когда возникает исключение, сеанс на сервере уничтожается и создается новый сеанс.