Spring Security 注销会话未失效

Posted

技术标签:

【中文标题】Spring Security 注销会话未失效【英文标题】:Spring Security Logout session is not invalidated 【发布时间】:2015-06-30 22:04:24 【问题描述】:

我几乎尝试了在 *** 和其他地方可以找到的所有方法来使其正常工作,但仍然无法正常工作。我正在使用 Spring Framework 4.1.6.RELEASE、Spring Security 4.0.0.RELEASE。我配置了命名空间注销标记,我能够使会话无效的唯一方法是在我的控制器中使用 HttpSession.invalidate() 调用以编程方式进行。

当请求注销时,我被重定向到相应的页面,但是会话永远不会失效并且 JSESSIONID 不会被删除。不,这不是缓存效果。我尝试了所有好的缓存建议,并且我有 @PreAuthorize 注释,我的用户必须经过身份验证才能调用它们,即使它注销也可以调用它们。使会话无效的唯一方法是在我被重定向并拒绝身份验证的登录面板中输入错误的用户名/密码。此时,会话被销毁。

我没有想法和提示。

这是我的 security-applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/security"
    xmlns:oauth="http://www.springframework.org/schema/security/oauth"
    xsi:schemaLocation="http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd
    http://www.springframework.org/schema/security/oauth
    http://www.springframework.org/schema/security/spring-security-oauth.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

<!-- -->
<b:bean id="securityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" >
    <b:property name="defaultRolePrefix" value="ROLE_" />
</b:bean>
<b:bean id="preInvocationAdvice" class="org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice" >
    <b:property name="expressionHandler" ref="securityExpressionHandler" />
</b:bean>
<b:bean id="postInvocationAdvice" class="org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice" >
    <b:constructor-arg ref="securityExpressionHandler" />
</b:bean>
<b:bean id="myRoleVoter" class="org.springframework.security.access.vote.RoleVoter">
    <b:property name="rolePrefix" value="ROLE_" />
</b:bean>
<!-- -->

<!-- Configuration de l'accès et du formulaire -->
<!-- Permettre l'accès libre aux feuilles de style, polices et images -->
<http pattern='/resources/css/**' security="none" />
<http pattern='/resources/fonts/**' security="none" />
<http pattern='/resources/images/**' security="none" />
<http pattern='/resources/js/**' security="none" />

<http use-expressions="true" disable-url-rewriting="true">

    <!-- Limitation à une seule session utilisateur concurrente -->
    <session-management invalid-session-url="/identite?session_invalide=1"
        session-authentication-error-url="/identite?identite_err=1">
        <concurrency-control max-sessions="1"
            expired-url="/identite?expiree=1" />
    </session-management>

    <!-- Définitions pour le formulaire de la page JSP d'identification -->
    <form-login login-page="/identite" login-processing-url="/identite.proc" default-target-url="/" always-use-default-target="true" authentication-failure-url="/identite?identite_err=1" username-parameter="username" password-parameter="password" />
    <csrf disabled="false" />

    <logout logout-url="/deconnexion"
        logout-success-url="/identite?termine=1"
        delete-cookies="JSESSIONID" invalidate-session="true"
         />

    <!-- Utiliser un canal chiffré pour les échanges -->
    <intercept-url requires-channel="https" pattern="/identite*" access="permitAll()" />
    <intercept-url requires-channel="https" pattern="/deconnexion*" access="permitAll()" />
    <intercept-url requires-channel="https" pattern="/logout*" access="permitAll()" />
    <intercept-url requires-channel="https" pattern="/action*" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_SUPPORT')" />
    <intercept-url requires-channel="https" pattern="/causes*" access="hasRole('ROLE_ADMIN')" />
    <intercept-url requires-channel="https" pattern="/telechargement*" access="hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')" />
    <intercept-url requires-channel="https" pattern="/**" access="isAuthenticated()" />
    <access-denied-handler error-page="/erreur403" />
</http>

<!-- Fournisseurs d'identité pour le formulaire -->
<authentication-manager erase-credentials="true">
    <authentication-provider ref="monFournisseurAD" />
</authentication-manager>
<b:bean id="grantedAuthoritiesMapper" class="com.company.gisti.securite.ad.ActiveDirectoryGrantedAuthoritiesMapper">
    <b:description>Cette fève (bean) met en place la correspondance entre les groupes AD/LDAP et les rôles au niveau applicatif.</b:description>
    <b:property name="groupesAdministrateur">
        <b:description>Ensemble de noms de groupes dans AD/LDAP indiquant que l'usager a un rôle d'administrateur pour cette application.</b:description>
        <b:set value-type="java.lang.String">
            <b:value>SecRole-Support-DDMI</b:value>
        </b:set>
    </b:property>
    <b:property name="groupesSupport">
        <b:description>Ensemble de noms de groupes dans AD/LDAP indiquant que l'usager a un rôle d'usager de support pour cette application.</b:description>
        <b:set value-type="java.lang.String">
            <b:value>SecRole-Support-HpSM</b:value>
            <b:value>SecRole-AdminSystemeHPUCMDB</b:value>
        </b:set>
    </b:property>
    <b:property name="groupesUsager">
        <b:description>Ensemble de noms de groupes dans AD/LDAP indiquant que l'usager a un rôle d'utilisateur simple pour cette application. </b:description>
        <b:set value-type="java.lang.String">
            <b:value>SecRole-Utilisateurs-HPAM</b:value>
        </b:set>
    </b:property>
</b:bean>

<!-- Identification par Active Directory -->
<b:bean id="monFournisseurAD" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <b:constructor-arg value="campus.company.com" />                <!-- userPrincipalName de la forme username@campus... -->
    <b:constructor-arg value="ldap://fsapps.company.uni:389/" />    <!-- Comment rejoindre le serveur -->
    <b:constructor-arg value="dc=fsapps,dc=company,dc=uni" />   <!-- baseObject -->
    <b:property name="searchFilter" value="(&amp;(userPrincipalName=0)(objectClass=user))" />
    <b:property name="userDetailsContextMapper">
        <b:bean class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" />
    </b:property>
    <b:property name="authoritiesMapper" ref="grantedAuthoritiesMapper" />
    <b:property name="convertSubErrorCodesToExceptions" value="true" />
</b:bean>

<b:bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
<b:bean id="myDeconnexionHandler" class="com.company.gisti.web.app.DeconnexionHandler" />

</b:beans>

这是我的 mvc-applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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-4.1.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd">

<security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />
<context:annotation-config />
<mvc:resources mapping="/resources/**" location="/resources/theme_desjardins/" />
<mvc:annotation-driven /><mvc:interceptors>
<mvc:interceptor>
    <mvc:mapping path="/**" />
    <bean class="org.springframework.web.servlet.mvc.WebContentInterceptor">
        <property name="cacheSeconds" value="0"></property>
        <property name="useExpiresHeader" value="true"></property>
        <property name="useCacheControlHeader" value="true"></property>
        <property name="useCacheControlNoStore" value="true"></property></bean>
</mvc:interceptor></mvc:interceptors>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/" />
    <property name="suffix" value=".jsp" />
</bean>

<context:component-scan base-package="com.company.gisti.web.app" />

</beans>

在我的安全 xml 文件中,定义了一个注销成功处理程序,我没有在此配置中使用它,但我尝试了一个,但从未调用它。我可能可以实现一个 logoutHandler,但此时它几乎等同于使会话无效,就像我在 servlet 控制器中所做的那样。


2015-04-23 11:06:00 EDT 更新

我的问题是注销 URL 是通过 GET 方法而不是 POST 访问的,因为它应该已经启用了 CSRF 保护。我更正了那部分,会话现在正确无效。唯一仍然不起作用的是重定向到登录页面。顺便说一句,我的注销 URL 是 /deconnexion,我的登录 URL 是 /identite。因此,会话实际上已失效并保留在同一页面上,但后台进程不再按预期授权,因为它们不再经过身份验证以访问服务器。由于 AccessDeniedException,我需要单击未经授权的 URL 以最终刷新页面。在下面的日志中,我没有给出点击此类 URL 的完整结果,该 URL 是日志中的 /causes。这将导致异常,然后将重定向到登录页面。日志前两行表示登录和页面加载成功完成,然后发起注销。

2015-04-23 11:01:40,040 DEBUG (o.s.w.s.FrameworkServlet.processRequest) [http-8443-1] Successfully completed request MDC
2015-04-23 11:01:40,040 DEBUG (o.s.s.w.a.ExceptionTranslationFilter.doFilter) [http-8443-1] Chain processed normally MDC
2015-04-23 11:01:40,040 DEBUG (o.s.s.w.c.SecurityContextPersistenceFilter.doFilter) [http-8443-1] SecurityContextHolder now cleared, as request processing completed MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/resources/css/**' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/resources/fonts/**' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/resources/images/**' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/resources/js/**' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /deconnexion at position 1 of 13 in additional filter chain; firing Filter: 'ChannelProcessingFilter' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/identite*' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/deconnexion*' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.a.c.ChannelProcessingFilter.doFilter) [http-8443-2] Request: FilterInvocation: URL: /deconnexion; ConfigAttributes: [REQUIRES_SECURE_CHANNEL] MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /deconnexion at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.c.HttpSessionSecurityContextRepository.readSecurityContextFromSession) [http-8443-2] Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@49e898d4: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@49e898d4: Principal: org.springframework.security.ldap.userdetails.InetOrgPerson@644dcdae: Dn: CN=MYUSERNAME,OU=Utilisateurs,DC=fsapps,DC=company,DC=uni; Username: myusername; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: SecRole-Support-DDMI, SecRole-Utilisateurs-HPAM; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe3f86: RemoteIpAddress: 127.0.0.1; SessionId: 783C021534873EBDFCCD914F8B7F1C8C; Granted Authorities: ROLE_ADMIN, ROLE_USER, ROLE_SUPPORT' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /deconnexion at position 3 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter' MDC
2015-04-23 11:01:43,020 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /deconnexion at position 4 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /deconnexion at position 5 of 13 in additional filter chain; firing Filter: 'CsrfFilter' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /deconnexion at position 6 of 13 in additional filter chain; firing Filter: 'LogoutFilter' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/deconnexion'; against '/deconnexion' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.a.l.LogoutFilter.doFilter) [http-8443-2] Logging out user 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@49e898d4: Principal: org.springframework.security.ldap.userdetails.InetOrgPerson@644dcdae: Dn: CN=MYUSERNAME,OU=Utilisateurs,DC=fsapps,DC=company,DC=uni; Username: myusername; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: SecRole-Support-DDMI, SecRole-Utilisateurs-HPAM; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe3f86: RemoteIpAddress: 127.0.0.1; SessionId: 783C021534873EBDFCCD914F8B7F1C8C; Granted Authorities: ROLE_ADMIN, ROLE_USER, ROLE_SUPPORT' and transferring to logout destination MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.a.l.SecurityContextLogoutHandler.logout) [http-8443-2] Invalidating session: 444589E454C7CDF3C9DBFC62E8CA0541 MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.s.HttpSessionEventPublisher.sessionDestroyed) [http-8443-2] Publishing event: org.springframework.security.web.session.HttpSessionDestroyedEvent[source=org.apache.catalina.session.StandardSessionFacade@565f0e7d] MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.c.s.SessionRegistryImpl.removeSessionInformation) [http-8443-2] Removing session 444589E454C7CDF3C9DBFC62E8CA0541 from principal's set of registered sessions MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.c.s.SessionRegistryImpl.removeSessionInformation) [http-8443-2] Removing principal org.springframework.security.ldap.userdetails.InetOrgPerson@644dcdae: Dn: CN=MYUSERNAME,OU=Utilisateurs,DC=fsapps,DC=company,DC=uni; Username: myusername; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: SecRole-Support-DDMI, SecRole-Utilisateurs-HPAM from registry MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.a.AbstractAuthenticationTargetUrlRequestHandler.determineTargetUrl) [http-8443-2] Using default Url: /identite MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.DefaultRedirectStrategy.sendRedirect) [http-8443-2] Redirecting to '/CaissesDispo/identite' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.c.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.saveContext) [http-8443-2] SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.c.SecurityContextPersistenceFilter.doFilter) [http-8443-2] SecurityContextHolder now cleared, as request processing completed MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/identite'; against '/resources/css/**' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/identite'; against '/resources/fonts/**' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/identite'; against '/resources/images/**' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/identite'; against '/resources/js/**' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 1 of 13 in additional filter chain; firing Filter: 'ChannelProcessingFilter' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/identite'; against '/identite*' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.a.c.ChannelProcessingFilter.doFilter) [http-8443-2] Request: FilterInvocation: URL: /identite; ConfigAttributes: [REQUIRES_SECURE_CHANNEL] MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.c.HttpSessionSecurityContextRepository.readSecurityContextFromSession) [http-8443-2] No HttpSession currently exists MDC
2015-04-23 11:01:43,035 DEBUG (o.s.s.w.c.HttpSessionSecurityContextRepository.loadContext) [http-8443-2] No SecurityContext was available from the HttpSession: null. A new one will be created. MDC
2015-04-23 11:01:43,051 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 3 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter' MDC
2015-04-23 11:01:43,051 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 4 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 5 of 13 in additional filter chain; firing Filter: 'CsrfFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 6 of 13 in additional filter chain; firing Filter: 'LogoutFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Request 'GET /identite' doesn't match 'POST /deconnexion MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 7 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Request 'GET /identite' doesn't match 'POST /identite.proc MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.a.AnonymousAuthenticationFilter.doFilter) [http-8443-2] Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/identite'; against '/identite*' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.a.i.AbstractSecurityInterceptor.beforeInvocation) [http-8443-2] Secure object: FilterInvocation: URL: /identite; Attributes: [permitAll()] MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.a.i.AbstractSecurityInterceptor.authenticateIfRequired) [http-8443-2] Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.a.v.AffirmativeBased.decide) [http-8443-2] Voter: org.springframework.security.web.access.expression.WebExpressionVoter@514ade37, returned: 1 MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.a.i.AbstractSecurityInterceptor.beforeInvocation) [http-8443-2] Authorization successful MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.a.i.AbstractSecurityInterceptor.beforeInvocation) [http-8443-2] RunAsManager did not change Authentication object MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter) [http-8443-2] /identite reached end of additional filter chain; proceeding with original chain MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.DispatcherServlet.doService) [http-8443-2] DispatcherServlet with name 'mvc-dispatcher' processing GET request for [/CaissesDispo/identite] MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.h.AbstractHandlerMethodMapping.getHandlerInternal) [http-8443-2] Looking up handler method for path /identite MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.h.AbstractHandlerMethodMapping.getHandlerInternal) [http-8443-2] Returning handler method [public java.lang.String com.company.gisti.web.app.ControleurIdentite.handleIdentiteJsp()] MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'controleurIdentite' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.DispatcherServlet.doDispatch) [http-8443-2] Last-Modified value for [/CaissesDispo/identite] is: -1 MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.m.WebContentInterceptor.preHandle) [http-8443-2] Looking up cache seconds for [/identite] MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.m.WebContentInterceptor.preHandle) [http-8443-2] Applying default cache seconds to [/identite] MDC
2015-04-23 11:01:43,052 INFO (c.d.g.w.c.ControleurIdentite.handleIdentiteJsp) [http-8443-2] ************************* >>>>>>> Redirige vers identite <<<<<<<<<<<<< *************** MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.DispatcherServlet.render) [http-8443-2] Rendering view [org.springframework.web.servlet.view.JstlView: name 'identite'; URL [/WEB-INF/pages/identite.jsp]] in DispatcherServlet with name 'mvc-dispatcher' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'requestDataValueProcessor' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.w.s.v.InternalResourceView.renderMergedOutputModel) [http-8443-2] Forwarding to resource [/WEB-INF/pages/identite.jsp] in InternalResourceView 'identite' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.s.w.s.HttpSessionEventPublisher.sessionCreated) [http-8443-2] Publishing event: org.springframework.security.web.session.HttpSessionCreatedEvent[source=org.apache.catalina.session.StandardSessionFacade@27573872] MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'securityExpressionHandler' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler#0' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'securityExpressionHandler' MDC
2015-04-23 11:01:43,052 DEBUG (o.s.b.f.s.AbstractBeanFactory.doGetBean) [http-8443-2] Returning cached instance of singleton bean 'org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler#0' MDC
2015-04-23 11:01:43,083 DEBUG (o.s.s.w.c.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.saveContext) [http-8443-2] SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. MDC
2015-04-23 11:01:43,083 DEBUG (o.s.w.s.FrameworkServlet.processRequest) [http-8443-2] Successfully completed request MDC
2015-04-23 11:01:43,083 DEBUG (o.s.s.w.a.ExceptionTranslationFilter.doFilter) [http-8443-2] Chain processed normally MDC
2015-04-23 11:01:43,083 DEBUG (o.s.s.w.c.SecurityContextPersistenceFilter.doFilter) [http-8443-2] SecurityContextHolder now cleared, as request processing completed MDC
2015-04-23 11:01:45,907 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/causes'; against '/resources/css/**' MDC
2015-04-23 11:01:45,907 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/causes'; against '/resources/fonts/**' MDC
2015-04-23 11:01:45,907 DEBUG (o.s.s.w.u.m.AntPathRequestMatcher.matches) [http-8443-2] Checking match of request : '/causes'; against '/resources/images/**' MDC

2015-04-23 14:37:00 更新已解决

我的问题解决了。由于我通过 ajax 发送了一个 POST 以注销,我收到了我应该从我的成功注销处理程序指向我的浏览器的 url。我必须使用 window.location.href = new_url 从我的 javascript 手动将浏览器指向此位置。

【问题讨论】:

如果启用了 csrf,您需要执行 POST 以注销。你是吗? 谢谢,这就是问题所在。我忘记启用 csrf 会对注销代码产生影响。我仍然有问题。我用 ajax 调用替换了我的 链接,注销正常完成,但是成功注销后我没有重定向到指定的页面。相反,我停留在同一页面上,并且必须单击菜单上未经授权的页面才能最终到达预期页面。日志非常密集,但基本上,我可以看到一个重定向,它不会在浏览器中触发任何内容,直到我单击将导致访问被拒绝异常的内容。 我在原始帖子中添加了我的日志的相关部分,因为我的答案有限。 【参考方案1】:

回答以便您可以结束您的问题。

如果您使用 Spring Security 的 CSRF 保护,您必须 POST 才能注销(尽管我相信这是可配置的)。

您可以使用 Javascript 但非 AJAX 执行注销 POST 吗?喜欢:

<!-- anywhere in your document: -->
<form:form action="deconnexion" id="logoutForm">
  <!-- csrf hidden input included automagically -->
</form:form>

<!-- in your menu: -->
<a href="#" onclick="document.forms.namedItem('logoutForm').submit()">Log out</a>

【讨论】:

我确实使用了 AJAX,因为我需要从下拉菜单中执行操作并且无法在其中插入表单。我在我的原始帖子中包含了带有 AJAX 请求的 javascript 代码。以及显示我浏览器中 Firebug 界面标题的两个屏幕截图,您可以在其中看到目标 URL 已实际接收,但浏览器不执行任何操作,除非我明确使用我从中获取的 URL 执行 window.location.href服务器。 伟大的提示尼尔。非常感谢。我不知道 Spring 标记库。我现在有太多要处理的事情,不能更仔细地看。它工作得很好,也更简单,代码更简洁。【参考方案2】:

2015-04-23 14:37:00 更新已解决

我的问题解决了。由于我通过 ajax 发送了一个 POST 以注销,我收到了我应该从我的成功注销处理程序指向我的浏览器的 url。我必须使用 window.location.href = new_url 从我的 javascript 手动将浏览器指向此位置。


2015-04-23 15:55:00更新跟进

注意:我必须将其放入单独的答案中,因为我达到了单个帖子中的字符数限制。

这是我的 javascript 代码的 sn-p,通过 ajax 发布请求注销:

    $('#deconnexion').click(function(event) 
        // Envoyer la requête
        var csrfToken = $("meta[name='_csrf']").attr("content");
        var csrfHeader = $("meta[name='_csrf_header']").attr("content");
        var csrf_header =  ;
        csrf_header[csrfHeader] = csrfToken;
        $.ajax(
            headers: csrf_header,
            url: 'deconnexion',
            processData: false,
            type: "POST",
            contentType: "text/xml",
            dataType: "text",
            success: function(data, textStatus, xhr) 
            /* */
                console.log("Etat rapporté: " + xhr.status);
                console.log("Données: " + data);
                console.log("Etat description: " + textStatus);
                console.log("reponseText: " + xhr.responseText);
                console.log("URL redirection: " + xhr.getResponseHeader("Location"));
            /*  */
                //window.location.href = xhr.getResponseHeader("Location");
            ,
            error: function(xhr, textStatus, thrownError) 
            /*
                console.log("Etat rapporté: " + xhr.status);
                console.log("Erreur description: " + thrownError);
                console.log("Etat description: " + textStatus);
                console.log("reponseText: " + xhr.responseText);
                */
                window.location.href = xhr.getResponseHeader("Location");
            
        );
    );

我还没有测试错误条件。在脚本中,window.location.href 被注释为测试。

以下是截图:

如果有什么可以让浏览器和 AJAX 完成这项工作,我很想知道如何做到这一点。

【讨论】:

以上是关于Spring Security 注销会话未失效的主要内容,如果未能解决你的问题,请参考以下文章

带有 LDAP 注销的 Spring Security 无法删除会话

java spring boot / spring security(HttpSecurity)中的会话到期时如何自动注销

当用户注销时,Spring Security 从数据库中删除会话

Spring Cloud Security 实战,退出登录时如何借助外力使JWT令牌失效?

您如何在 spring-security 中注销所有已登录的用户?

Spring Security WebFlux 注销