如何在春季注销前执行操作?

如何在春季注销前执行操作?

问题描述:

首先,这不是一个重复的问题,我检查了答案here!和 here!但无法让它工作。如何在春季注销前执行操作?

另外我想在注销前执行它,所以不能使用logoutSuccessHandler。

所以我需要创建一个自定义的LOGOUT_FILTER,我真的很难得到它的工作。

这里是我的春天,安全XML中,我尝试了两种方法 首先是: -

<custom-filter ref="logoutFilter" position="LOGOUT_FILTER" /> 

<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
<beans:constructor-arg index="0" value="/logoutSuccess" /> 
<beans:constructor-arg index="1"> 
    <beans:list> 
     <beans:bean id="securityContextLogoutHandler" 
     class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" /> 
    <beans:bean id="myLogoutHandler" class="com.fe.cms.listener.SimpleLogoutHandler" /> 
    </beans:list> 
</beans:constructor-arg> 
<beans:property name="filterProcessesUrl" value="/logout" /> 
</beans:bean> 

,但是这给了我错误

Configuration problem: Security namespace does not support decoration of element [custom-filter] 

然后我尝试..

<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
    <beans:constructor-arg index="0" value="/logout" /> 
    <beans:constructor-arg index="1"> 
     <beans:ref bean="securityContextLogoutHandler" /> 
     <beans:ref bean="myLogoutHandler" /> 
    </beans:constructor-arg> 
    <beans:property name="filterProcessesUrl" value="/logout" /> 
</beans:bean> 

<beans:bean id="securityContextLogoutHandler" 
    class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" /> 

<beans:bean id="myLogoutHandler" class="com.fe.cms.listener.SimpleLogoutHandler" /> 

<http auto-config="false" entry-point-ref="authenticationManger"> 
    <custom-filter ref="logoutFilter" position="LOGOUT_FILTER" /> 
</http> 

但这给了我错误: -

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#48' while setting bean property 'sourceList' with key [48]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#48': Cannot create inner bean '(inner bean)' of type [org.springframework.security.web.access.ExceptionTranslationFilter] while setting constructor argument with key [6]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#181': Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities) 

请谁能告诉我在哪里做错了.. 我将发布完整的XML文件,如果需要的话

+0

描述你还想要什么,我怀疑你需要一个自定义注销过滤器,因为它可能可以通过添加到其他LogoutHandler链中的LogoutHandler来完成。但是,由于你不知道你想达到什么(功能上),很难说。 – 2014-11-21 08:31:29

+0

@ M.Deinum当会话即将销毁时,我实际上想对会话数据执行一些操作。希望现在明确 – 2014-11-21 09:50:00

+0

然后,只需编写一个'ApplicationListener'来监听'HttpSessionDestroyedEvent's。还要将'HttpSessionEventPublisher'注册到您的web.xml中。通过这种方式,您还可以处理超时的会话,而不仅仅是定期注销。 – 2014-11-21 09:52:00

替换默认LogoutFilter根据你澄清你想要的是获得访问会话和执行一些逻辑。而不是用自定义LogoutFilter窃听,只需编写一个ApplicationListener即可听取HttpSessionDestroyedEvent s。

@Component 
public class SessionListener implements ApplicationListener<HttpSessionDestroyedEvent> { 

    public void onApplicationEvent(HttpSessionDestroyedEvent evt) { 
     HttpSession session = evt.getSession(); 
     // Your logic here 
    } 
} 

为了能够重新获得活动确保你在web.xml注册HttpSessionEventPublisher

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

此解决方案的主要优点是,您还可以处理会话超时而不仅仅是常规注销。

+0

我试过这种方法,它导致像'SecurityContextLogoutHandler'拦截器..logout方法甚至在已经破坏会话的监听器之前调用.... – 2014-11-21 10:14:58

+0

不,它不是因为会话仍然存在,因为它在**毁灭期间被称为**。参数和安全上下文仍然存在。还要确保你注册了监听器(否则它不会工作)。无论如何,你想用这个会话做什么? – 2014-11-21 10:19:10

+0

是的,我注册了它,它被称为罚款..我有一个会话范围的bean,我把一些数据在用户登录时在bean上,只是想在用户注销时执行一些操作的数据 – 2014-11-21 10:21:51

如果您需要执行一些操作之前注销,我想春天拦截可以帮助你。

您可以实现一类是这样的:

public class JustBeforeLogoutInterceptor extends HandlerInterceptorAdapter { 

    @Override 
    public boolean preHandle(HttpServletRequest request, 
      HttpServletResponse response, Object handler) throws Exception { 
     boolean res = super.preHandle(request, response, handler); 
     // 
     // your code... 
     // 
     return res; 
    } 
} 

然后,你需要配置拦截器:

<mvc:interceptors> 
    <mvc:interceptor> 
     <mvc:mapping path="/logout" /> 
     <bean class="your.app.JustBeforeLogoutInterceptor" /> 
    </mvc:interceptor> 
</mvc:interceptors> 

这应该工作。尝试一下。

+0

这似乎是一个更好的解决方案:) – 2014-11-21 09:25:50

+0

感谢@davioooh但'SecurityContextLogoutHandler'的注销方法甚至在拦截器之前被调用..所以到达拦截器时,会话实际上已经被破坏.. – 2014-11-21 09:48:07

在调用超类doFilter方法之前,您可以尝试扩展当前LogoutFilter并执行您的自定义逻辑。

像这样

public class CustomLogoutFilter extends LogoutFilter { 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
      throws IOException, ServletException { 
     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 

     if (requiresLogout(request, response)) { 
      // IMPLEMENT YOUR CUSTOM LOGIC HERE 

      super.doFilter(req, res, chain); 

      return; 
     } 

     chain.doFilter(request, response); 
    } 

} 

然后,你必须与你的CustomLogoutFilter

<http> 
    <custom-filter position="LOGOUT_FILTER" ref="customLogoutFilter" /> 
</http> 

<bean id="customLogutFilter" class="example.CustomLogoutFilter"> 
    <property name="filterProcessesUrl" value="/logout" /> 
    <!-- Put other needed properties here--> 
</bean> 
+0

那就是如果你看到我的问题,我做了什么......创建了一个注销处理程序'myLogoutHandler',并且我正面临一个错误。 – 2014-11-21 10:02:10

+0

在你的问题中,你可以简单地用默认的过滤器实现,用不同的属性覆盖默认的过滤器。我建议基于默认注销过滤器实现来实现您自己的LogoutFilter。你遇到的错误很奇怪,并提示一个命名空间问题,这可能是XML配置中的语法问题。你能否在你的问题中添加你的XML配置? //此外,你可以尝试davioooh的解决方案,它似乎更好。 – 2014-11-21 10:13:06