如何使用Spring Security手动注销用户?


72

答案可能很简单:如何在Spring Security中手动注销当前登录的用户?致电是否足够:

SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false); 


非常感谢您的回答,伙计们,我会检查出来的。
Erik

Answers:


40

在Servlet 3.0容器中,Spring注销功能与Servlet集成在一起,您只需logout()在上调用HttpServletRequest。仍然需要编写有效的响应内容。

根据文档(Spring 3.2):

HttpServletRequest.logout()方法可用于注销当前用户。

通常,这意味着将清除SecurityContextHolder,使HttpSession无效,将清除所有“记住我”身份验证,依此类推。


org.apache.catalina.connector.Request#logoutSpring 3.1.2 / Grails 2.2.0的Tomcat 7实施中拥有NPE 。没有这样的错误clearContext()
帕维尔·弗拉索夫

@PavelVlasov我相信这是弹簧配置中的一些错误,请阅读有关SecurityContextHolder的信息。
PiotrMüller'15

3
request.logout()我仍然具有以下SecurityContextHolder.getContext().getAuthentication()
身份的

72

我很难确定您的代码是否足够。但是,标准Spring-security的注销实现不同。如果您看一看,SecurityContextLogoutHandler您会看到它们的作用:

    SecurityContextHolder.clearContext();

此外,它们还可以选择使HttpSession无效:

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

您可以在其他有关在Spring Security中注销和查看的源代码的org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler其他问题中找到更多信息。


2
如果已设置,您还需要删除Rememberme Cookie。
sourcedelica

24

我在LogoutFilter中使用相同的代码,重新使用LogoutHandlers如下:

public static void myLogoff(HttpServletRequest request, HttpServletResponse response) {
    CookieClearingLogoutHandler cookieClearingLogoutHandler = new CookieClearingLogoutHandler(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
    SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
    cookieClearingLogoutHandler.logout(request, response, null);
    securityContextLogoutHandler.logout(request, response, null);
}

由于CookieClearingLogoutHandler +1,否则,如果用户拥有“记住我” cookie,则可以再次登录。请注意,该课程要求春季3.1
redochka

10

您还可以将SessionRegistry用作:

sessionRegistry.getSessionInformation(sessionId).expireNow();

如果要在用户的所有会话中强制注销,请使用getAllSessions方法和expireNow每个会话信息的调用。

编辑
这需要ConcurrentSessionFilter(或链中的其他任何过滤器)检查SessionInformation并调用所有注销处理程序,然后进行重定向。


10

要注销Web应用程序中的用户,您还可以将其重定向到注销页面。然后,LogoutFilter为您完成所有工作。

在安全配置中设置注销页面的URL:

<sec:http ...>
  ...
  <sec:logout logout-url="/logout" logout-success-url="/login?logout_successful=1" />
  ...
</sec:http>

1
这对我没有用。它不像您建议的那么简单。还有更多配置详细信息吗?
djangofan 2012年

不需要其他配置即可运行。您只需将用户重定向到类似“ example.com/yourctx/logout ”的URL 。
詹姆斯

我可以正常工作,但是必须重新启动Tomcat才能开始工作。
djangofan 2012年

3

new SecurityContextLogoutHandler().logout(request, null, null);


2

只需这样做(通过“关注您”评论的人)即可:

    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); // concern you

    User currUser = userService.getUserById(auth.getName()); // some of DAO or Service...

    SecurityContextLogoutHandler ctxLogOut = new SecurityContextLogoutHandler(); // concern you

    if( currUser == null ){
        ctxLogOut.logout(request, response, auth); // concern you
    }

2

最近,我们不得不使用Spring-security 3.0.5实现注销功能。尽管上面已经回答了这个问题,但我将发布完整的代码,这肯定会对像我这样的新手有所帮助:)

Spring-security.xml中的配置

 <http auto-config="false" lowercase-comparisons="false" use-expressions="true">
     <custom-filter position="LOGOUT_FILTER" ref="logoutFilter" />
 </http>

<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <beans:constructor-arg name="logoutSuccessHandler" ref="xxxLogoutSuccessHandler" />
    <beans:constructor-arg name="handlers">
        <beans:list>
            <beans:ref bean="securityContextLogoutHandler"/>
            <beans:ref bean="xxxLogoutHandler"/>
        </beans:list>
    </beans:constructor-arg>
    <beans:property name="filterProcessesUrl" value="/logout"/>
</beans:bean>
<beans:bean id="XXXLogoutSuccessHandler" class="com.tms.dis.sso.XXXLogoutSuccessHandler"/>
<beans:bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
    <beans:property name="invalidateHttpSession" value="true"/>
</beans:bean>
<beans:bean id="XXXLogoutHandler" class="com.tms.dis.sso.XXXLogoutHandler"/>

在这里,我创建了两个自定义类

  1. XXXLogoutHandler,它将实现org.springframework.security.web.authentication.logout.LogoutHandler并将覆盖logout()方法。
  2. XXXLogoutSuccessHandler,它将实现org.springframework.security.web.authentication.logout.LogoutSuccessHanlder并将覆盖onLoguoutSuccess()方法。在XXXLogoutSuccessHandler.onLogoutSuccess()方法中,调用redirectStrategy.sendRedirect()方法,该方法将用户注销到特定的targetURL。
  3. org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler执行使用户会话无效的任务。

希望这会有所帮助并为初学者提供正确的方向

注意:故意没有发布自定义实现的代码。


1

对了,Oledzki,我在控制器内部使用了以下示例,以注销用户并将其重定向到Spring Security 4.2.3中的登录页面。

SecurityContextHolder.clearContext();

if(session != null)
    session.invalidate();

return "redirect:/login";
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.