2012-09-25 82 views
1

我正在開發一個Java + Spring MVC + Hibernate + Spring Security 3.1的webapp。當我註銷而不是僅重定向到登錄頁面時,它會轉到會話過期方法,以便顯示登錄頁面,但會話過期!消息...Spring Security 3.1:註銷後捕獲會話過期

這裏是安全的context.xml

<?xml version="1.0" encoding="ISO-8859-1"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:security="http://www.springframework.org/schema/security" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <security:debug /> 

    <!-- preauthentication -->  
    <security:global-method-security pre-post-annotations="enabled"> 
    </security:global-method-security> 

    <security:http auto-config="false" use-expressions="true" entry-point-ref="http403EntryPoint" access-denied-page="/errores/accesodenegado"> 
     <security:intercept-url pattern="/" access="permitAll"/> 
     <security:intercept-url pattern="/error.jsp" access="permitAll"/> 
     <!-- Allow non-secure access to static resources --> 
     <security:intercept-url pattern="/resources/**" access="permitAll"/> 
     <security:intercept-url pattern="/autenticacion/**" access="permitAll"/> 
     <security:intercept-url pattern="/errores/**" access="permitAll"/> 
     <!-- URLs que dependen de perfiles --> 
     <security:intercept-url pattern="/gestion/facturas/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN','ROLE_CONSL')"/> 
     <security:intercept-url pattern="/gestion/tarifas/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN','ROLE_CONSL')"/> 
     <security:intercept-url pattern="/gestion/envios/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN')"/> 
     <security:intercept-url pattern="/gestion/perfiles/**" access="hasRole('ROLE_ADMIN')"/> 
     <security:intercept-url pattern="/gestion/usuarios/**" access="hasRole('ROLE_ADMIN')"/> 
     <security:intercept-url pattern="/consulta/**" access="hasAnyRole('ROLE_CONSL','ROLE_ADMIN','ROLE_S_CEN')"/> 
     <security:intercept-url pattern="/importacion/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN')"/> 
     <!-- Pantalla a la que redirige el logout -->   
     <security:logout logout-success-url="/" delete-cookies="JSESSIONID"/> 
     <!-- El session timeout lleva a la pantalla de login --> 
     <security:session-management invalid-session-url="/errores/sesionexpirada" /> 
    </security:http> 

    <bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"> 
    </bean> 

    <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> 
     <security:filter-chain-map path-type="ant"> 
      <security:filter-chain pattern="/**" filters="j2eePreAuthFilter"/> 
     </security:filter-chain-map> 
    </bean> 

    <security:authentication-manager alias="authenticationManager"> 
     <security:authentication-provider ref='preAuthenticatedAuthenticationProvider'/> 
    </security:authentication-manager> 

    <bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"> 
     <property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService"/> 
    </bean> 

    <bean id="preAuthenticatedUserDetailsService" 
      class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"/> 


    <bean id="j2eePreAuthFilter" class="es.myApp.security.MyAppUserJ2eePreAuthenticatedProcessingFilter"> 
     <property name="authenticationManager" ref="authenticationManager"/> 
     <property name="authenticationDetailsSource" ref="authenticationDetailsSource"/> 
     <property name="continueFilterChainOnUnsuccessfulAuthentication" value="false"/> 
    </bean> 

    <bean id="authenticationDetailsSource" class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"> 
     <property name="mappableRolesRetriever" ref="j2eeMappableRolesRetriever"/> 
     <property name="userRoles2GrantedAuthoritiesMapper" ref="j2eeUserRoles2GrantedAuthoritiesMapper"/> 
    </bean> 

    <bean id="j2eeMappableRolesRetriever" class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever"> 
    </bean> 

    <bean id="j2eeUserRoles2GrantedAuthoritiesMapper" class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper"> 
     <property name="attributePrefix" value="test"/> 
    </bean> 

</beans> 

註銷按鈕調用:

@Controller 
@RequestMapping("/autenticacion") 
public class AutenticacionController { 

[...] 

@RequestMapping(value = "salir") 
    public String salir(Model model, HttpServletRequest request, HttpServletResponse response) {   
//  request.getSession().removeAttribute(Constantes.USUARIO_SESION); 
//  request.getSession().invalidate(); 
     return "redirect:/j_spring_security_logout"; 
    } 
} 

我試着註釋掉那些線條和使用它們,但行爲是完全相同... Constantes.USUARIO_SESION在會話中存儲用戶變量的名稱。

日誌的方法執行,除其他事項外:

request.getSession().setAttribute(Constantes.USUARIO_SESION, usuario); 

UserDetails userDetails = myAppUserDetailsService.loadUserByUsername(usuario.getLogin()); 
Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 
          SecurityContextHolder.getContext().setAuthentication(auth); 

會話過期經歷:

@RequestMapping("sesionexpirada") 
    public String sesionExpirada(Model model, HttpServletRequest request, HttpServletResponse response) { 
    MessageManager msgManager = new MessageManager(); 

    msgManager.addError("error.sesion.expirada"); 
    request.getSession().setAttribute("messageManager", msgManager); 

    return "inicio"; 
} 

和web.xml

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 

    <display-name>Aplicación Web MyApp</display-name> 

    <!-- Define la localización de los ficheros de configuración de Spring --> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/classes/applicationContext.xml 
     </param-value> 
    </context-param> 

    <!-- Reads request input using UTF-8 encoding --> 
    <filter> 
     <filter-name>characterEncodingFilter</filter-name> 
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
     <init-param> 
      <param-name>encoding</param-name> 
      <param-value>UTF-8</param-value> 
     </init-param> 
     <init-param> 
      <param-name>forceEncoding</param-name> 
      <param-value>true</param-value> 
     </init-param> 
    </filter> 

    <filter-mapping> 
     <filter-name>characterEncodingFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 

    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <filter> 
     <filter-name>myAppUserJ2eePreAuthenticatedProcessingFilter</filter-name> 
     <filter-class>es.myApp.security.XiscoUserJ2eePreAuthenticatedProcessingFilter</filter-class> 
    </filter> 

    <filter-mapping> 
     <filter-name>myAppUserJ2eePreAuthenticatedProcessingFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <!-- Handles all requests into the application --> 
    <servlet> 
     <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> 
     <servlet-class>es.myApp.controller.XiscoDispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>/WEB-INF/servlet-context.xml</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 

    <!-- del. welcome files --> 
    <!-- useful for Servlet 3 container (Tomcat 7 and Jetty 6) --> 
    <welcome-file-list> 
     <welcome-file></welcome-file> 
    </welcome-file-list> 

    <!-- Página de error --> 
    <error-page> 
     <error-code>404</error-code> 
     <location>/errores/error</location> 
    </error-page> 

    <!-- Tiempo de sesión --> 
    <session-config> 
     <session-timeout>15</session-timeout> 
    </session-config> 

    <listener> 
     <listener-class> 
      org.springframework.security.web.session.HttpSessionEventPublisher 
     </listener-class> 
    </listener> 

    <!-- Referencia a recursos jndi WAS --> 
    <resource-ref id="ResourceRef_MyApp> 
     <res-ref-name>jdbc/myApp</res-ref-name> 
     <res-type>javax.sql.DataSource</res-type> 
     <res-auth>Container</res-auth> 
     <res-sharing-scope>Shareable</res-sharing-scope> 
    </resource-ref> 

</web-app> 

我測試了它在Tomcat 6和WAS 8.5 ...

編輯:如果我擺脫Spring Security的註銷,並實現自己的它按預期工作:

我抹去:<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>從安全的context.xml和改變被稱爲上登出的方法:

@RequestMapping("salir") 
    public String salir(Model model, HttpServletRequest request, HttpServletResponse response) {   
     request.getSession().removeAttribute(Constantes.USUARIO_SESION); 

     HttpSession session = request.getSession(false); 
     if (session != null) { 
      session.invalidate(); 
     } 
     SecurityContextHolder.clearContext(); 

     return "inicio"; 
    } 

它爲什麼現在工作?這些代碼行取自Spring的註銷代碼...

回答

0

我不明白你在做什麼。您編寫了自己的控制器,使會話失效,然後重定向到Spring安全註銷URL。該控制器是不必要的,只需直接使用彈出註銷URL,默認情況下它會使您的會話失效。如果您需要在註銷時添加特殊行爲,請編寫您自己的LogoutSuccessHandler或擴展其中一個彈簧處理程序並將其添加到LogoutFilter。

+0

它僅用於測試目的...即使控制器只重定向到Spring註銷它也不能正常工作,我的意思是,您單擊註銷按鈕,Spring執行它的操作,然後將其用於會話過期的過濾器...所以當我嘗試註銷時,我最終進入了登錄頁面,但是「會話過期!」警告......這是我試圖避免但無法完成的,這就是我編寫控制器的原因,如果我不轉發到Spring的註銷並執行我自己的代碼,它可以工作...... – diminuta

1

您需要添加

<security:session-management session-fixation-protection="none"/> 

security:http部分。