Spring Security自定义LogoutSuccessHandler获取奇怪的Authentication对象

时间:2012-07-16 11:09:41

标签: spring spring-mvc spring-security logout

我正在使用Spring Security(3.1)开发一个应用程序,我遇到了以下问题。当用户注销时,我想重定向到某个自定义URL,具体取决于他是否从安全页面注销。我写了一个自定义的LogoutHandler,看起来如下:

@Override
public void onLogoutSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication authentication)
        throws IOException, ServletException {


    String refererUrl = request.getHeader("Referer");
    if (requiredAuthentication(refererUrl, authentication)) {
        response.sendRedirect(request.getContextPath());
    } else {
        response.sendRedirect(refererUrl);
    }
}

private boolean requiredAuthentication(String url, Authentication authentication){
    return !getPrivilegeEvaluator().isAllowed(url, authentication);
}

因此,当用户从非安全页面注销时,他将被注销并重定向到相同的URL,如果他从安全页面登录,则会转到索引页面。 问题是,访问该方法的Authentication对象始终是经过身份验证的(即使该方法根据规范在用户登录后调用)。 我的安全背景:

<http use-expressions="true" disable-url-rewriting="true" request-matcher-ref="requestMatcher" >


    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" requires-channel="https" />
    <intercept-url pattern="/dashboard/**" access="hasRole('ROLE_OWNER')" requires-channel="https" />
    <intercept-url pattern="/**" access="permitAll"/>

    <form-login login-page="/login"
                authentication-success-handler-ref="successHandler"
                authentication-failure-url="/login"
                login-processing-url="/validate"  />

    <logout logout-url="/logout" invalidate-session="true" success-handler-ref="logoutSuccessHandler" />

    <remember-me services-ref="rememberMeServices" key="KEY"  use-secure-cookie="false" />

    <session-management session-fixation-protection="migrateSession">
        <concurrency-control max-sessions="1" />
    </session-management>

</http>

你有什么想法,为什么收到身份验证仍然有效,当gettig到logoutSuccessHandler?我无法编辑此对象,因为它的字段是最终的(除了isAuthenticated,但它没有被isAllowed()方法检查..)

1 个答案:

答案 0 :(得分:3)

查看Spring Security源代码,LogoutFilter从SecurityContextHolder获取Authentication对象,将其保存在本地变量上,并通过SecurityContextLogoutHandler将其从持有者中删除。调用所有LogoutHandler后,它会调用LogoutSuccessHandler,并传递Authentication对象。

即使它说它有效,它也不再存在于SecurityContextHolder中,因此对于Spring,用户已经注销。