SpringSecurity:无法删除JSESSIONID

use*_*823 6 spring spring-mvc spring-security

我需要在用户注销时删除cookie JSESSIONID.为此,我将以下配置添加到我的安全配置中:

<http>
    <form-login login-page="/login*" authentication-failure-url="/login?try_again" />
    <http-basic />
    <logout logout-url="/logout" delete-cookies="JSESSIONID" />
    <session-management invalid-session-url="/timeout" />

    <intercept-url pattern="/login*"    access="IS_AUTHENTICATED_ANONYMOUSLY" />

    ...

</http>
Run Code Online (Sandbox Code Playgroud)

但是,cookie不会被删除,而是变得重复:

老饼干

新的cookie

所以它一直将浏览器重定向到"/ timeout"URL.

我尝试使用Chrome网络浏览器中的开发人员工具跟踪正在发生的事情,我发现此Cookie设置了此响应标头:

Set-Cookie:JSESSIONID=CFF85EA743724F23FDA0317A75CFAD44; Path=/website/; HttpOnly
Run Code Online (Sandbox Code Playgroud)

并使用此响应标头删除:

Set-Cookie:JSESSIONID=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/website
Run Code Online (Sandbox Code Playgroud)

我不确定,但似乎原因在于这些标题的"路径"字段:在第一个中它指向"/ website /",在第二个中它指向"/ website".

这是所描述的麻烦的原因吗?如果不是原因(或不是唯一原因),那么其他原因是什么?我该如何解决这个问题呢?

zag*_*gyi 6

您不需要JSESSIONID像这样明确删除cookie.它不是由Spring Security管理的,而是由您的servlet容器管理的.默认情况下,Spring Security将在注销时使http会话无效,这反过来会导致您的servlet容器删除JSESSIONIDcookie.

  • http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-session-mgmt显示如果您使用会话管理标记,则可能需要明确删除cookie. (2认同)

Not*_*aeL 5

在我的情况下,由于某种原因,即使SecurityContextLogoutHandler调用session.invalidate() JSESSIONID也不会被清除。它的价值保持不变。

我尝试使用delete-cookies="JSESSIONID"OP 尝试过的相同方式,我相信我遇到了同样的问题:为 cookie 设置的路径/是末尾没有 a 的上下文路径,所以它仍然不会被清除(它给出了命令删除不存在的cookie)。

我最终编写了自己的ProperCookieClearLogoutHandler,它与CookieClearLogoutHandler相同,除了设置 cookie 的上下文路径的行:

package com.testdomain.testpackage;

import java.util.Arrays;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

public final class ProperCookieClearingLogoutHandler implements LogoutHandler {
    private final List<String> cookiesToClear;

    public ProperCookieClearingLogoutHandler(String... cookiesToClear) {
        Assert.notNull(cookiesToClear, "List of cookies cannot be null");
        this.cookiesToClear = Arrays.asList(cookiesToClear);
    }

    public void logout(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) {
        for (String cookieName : cookiesToClear) {
            Cookie cookie = new Cookie(cookieName, null);
            String cookiePath = request.getContextPath() + "/";
            if (!StringUtils.hasLength(cookiePath)) {
                cookiePath = "/";
            }
            cookie.setPath(cookiePath);
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我以这种方式设置LogoutFilter的配置spring-security.xml

    <bean id="logoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg name="logoutSuccessUrl" value="/views/login/login.xhtml?logout" />
        <constructor-arg>
            <list>
                <bean id="properCookieClearingLogoutHandler"
                    class="com.imatia.arpad.gplenos.authorization.ProperCookieClearingLogoutHandler">
                    <constructor-arg name="cookiesToClear">
                        <list>
                            <value>JSESSIONID</value>
                        </list>
                    </constructor-arg>
                </bean>
                <bean id="securityContextLogoutHandler"
                    class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
                </bean>
            </list>
        </constructor-arg>
        <property name="filterProcessesUrl" value="/logout" />
    </bean>
Run Code Online (Sandbox Code Playgroud)