jsf spring安全会话超时viewExpiredException

jsf spring安全会话超时viewExpiredException,jsf,redirect,spring-security,timeout,viewexpiredexception,Jsf,Redirect,Spring Security,Timeout,Viewexpiredexception,我对使用JSF的Spring Security中的超时有以下问题: 我已经自定义了sessionmanagement筛选器,以便仅当请求的页面受到保护时(即仅允许经过身份验证的用户使用该页面),才将用户重定向到invalidSessionUrl。我放入Spring Security提供的会话管理过滤器中的自定义代码是: if (invalidSessionUrl != null) { String pagSolicitada = UtilSpringSecurity.extraerPa

我对使用JSF的Spring Security中的超时有以下问题:

我已经自定义了sessionmanagement筛选器,以便仅当请求的页面受到保护时(即仅允许经过身份验证的用户使用该页面),才将用户重定向到invalidSessionUrl。我放入Spring Security提供的会话管理过滤器中的自定义代码是:

if (invalidSessionUrl != null) {
     String pagSolicitada = UtilSpringSecurity.extraerPagina(request);
     if ( UtilSpringSecurity.paginaAutenticada(pagSolicitada ) ) {
          request.getSession();
          redirectStrategy.sendRedirect(request, response, invalidSessionUrl);
          return;
     }
     //the requested page doesn't require the user to be authenticated
     //so i just skip this filter and continue with the filter chain
     chain.doFilter(request, response);
     return;
}
“UtilSpringSecurity.extraerPagina(请求)”方法通过以下方式返回请求的页面:

public static String extraerPagina (HttpServletRequest request) {
     String uri = request.getRequestURI().toLowerCase();
     String cPath = request.getContextPath().toLowerCase();
     // uri = cPath + pagina
     int longCPath = cPath.length();
     String pagina = uri.substring(longCPath);
     return pagina;
}
@Override
public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
     UIViewRoot root = wrapped.restoreView(facesContext, viewId);
     if(root == null) {
          root = createView(facesContext, viewId);
     }
     return root;
}
如果参数是需要对用户进行身份验证的页面,则方法“UtilSpringSecurity.paginaAutenticada(paglocarketada)”返回true(考虑到xml安全配置文件中具有属性
access=“isAuthenticated()”
)的拦截url元素,我使用IFs进行检查:

此解决方案可行,但它只有一个问题:

如果我让浏览器在某个页面处于空闲状态,直到会话超时过期,然后我请求同一页面,那么我会得到一个“viewExpiredException”。这是因为过滤器工作正常,它绕过了对invalidSessionUrl的重定向,但由于会话无论如何都已过期,因此我在尝试重新呈现相同页面时遇到异常

如果我在会话超时过期时请求任何其他不安全的页面,它工作正常,会正确重定向到该页面,并且我不会得到viewExpiredException

有人知道怎么解决这个问题吗


提前感谢。

Spring security应该允许您匿名访问未经身份验证的用户的页面集。下面是我如何实现这一点的XML配置摘录

<http auto-config="true" access-denied-page="/unauthorized.xhtml" >
    <intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
    <intercept-url pattern="/app/**" access="ROLE_USER,ROLE_ADMIN" />
    <intercept-url pattern="/*.xhtml" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <form-login login-page="/login.xhtml" login-processing-url="/j_spring_security_check"
        authentication-success-handler-ref="authenticationSuccessBean"
        authentication-failure-handler-ref="authenticationFailureBean"  />
    <session-management invalid-session-url="/login.xhtml" >
    </session-management>
</http>

我基本上使用
intercept url
标记来声明某些相对上下文中的页面只能由以下角色访问。您可以看到,匿名用户可以使用web应用程序默认上下文中的所有页面。如果用户未经授权查看页面,则他们将被重定向到
拒绝访问页面


唯一需要注意的是,您的用户bean必须实现
UserDetails
接口,并且具有一个返回角色bean的属性,该角色bean实现
GrantedAuthority
接口。Spring将寻找一个
UserDetails
来拥有一个
GrantedAuthority
属性来确定角色是什么。如果此用户不存在、未经身份验证或未知,则它将默认为匿名角色。

最后我解决了它。这是一个JSF问题,与Spring安全性无关

我通过以下方式覆盖了jsf的restoreView方法:

public static String extraerPagina (HttpServletRequest request) {
     String uri = request.getRequestURI().toLowerCase();
     String cPath = request.getContextPath().toLowerCase();
     // uri = cPath + pagina
     int longCPath = cPath.length();
     String pagina = uri.substring(longCPath);
     return pagina;
}
@Override
public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
     UIViewRoot root = wrapped.restoreView(facesContext, viewId);
     if(root == null) {
          root = createView(facesContext, viewId);
     }
     return root;
}

现在的问题是,如果页面有参数,我在发布到最近创建的视图时丢失了参数,但这是另一个不同的问题(PRG模式),再次处理JSF。

它绕过了对invalidSessionUrl的重定向,但由于会话仍然过期,然后,我尝试重新呈现同一页面时出现异常。
我不明白这意味着什么。你是说当你重新提交invalidSessionUrl时,你会得到一个ViewExpiredException?你为什么要编写自己的会话管理过滤器?Spring security为您提供了这种现成的功能。只需将以下内容添加到SpringXML配置
回答您的第一条评论:
它绕过了对invalidSessionUrl的重定向,但由于会话无论如何都已过期,因此我在尝试重新呈现同一页面时遇到异常
。我的意思是,当我重新呈现浏览器在超时时显示的不安全页面时,我得到了“viewExpiredException”。这是因为JSF无法构建页面视图,因为会话已过期。Spring Security跳过会话管理过滤器,因为页面不安全(这没问题),但是当JSF尝试重新呈现页面时,它会抛出异常。回答您的第二条评论:Spring Security没有提供我想要的现成功能。我想跳过未受保护的请求页面的会话管理筛选器。默认过滤器没有实现这一点,也不能通过xml进行配置。这就是我编写自己的过滤器的原因,与默认过滤器相同,但添加检查以查看请求的页面是否安全。如果它不安全,我会跳过过滤器,以免重定向到invalidSessionUrl。我知道你说的,但那不是我想要的。根据您的场景,如果任何用户(无论是否经过身份验证)请求具有访问属性“已匿名身份验证”的页面(即与模式“/*.xhtml”匹配且不在管理员或应用程序目录中的任何页面),则当会话为timedout时,sesion management筛选器会将其重定向到invali会话url。但是我想要的不是重定向到无效的会话url,在这种情况下,只需显示我请求的页面,就好像会话没有timedout一样(即,在这种情况下不应用会话管理筛选器)