如何在春季注销前执行操作?
首先,这不是一个重复的问题,我检查了答案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文件,如果需要的话
替换默认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>
此解决方案的主要优点是,您还可以处理会话超时而不仅仅是常规注销。
我试过这种方法,它导致像'SecurityContextLogoutHandler'拦截器..logout方法甚至在已经破坏会话的监听器之前调用.... – 2014-11-21 10:14:58
不,它不是因为会话仍然存在,因为它在**毁灭期间被称为**。参数和安全上下文仍然存在。还要确保你注册了监听器(否则它不会工作)。无论如何,你想用这个会话做什么? – 2014-11-21 10:19:10
是的,我注册了它,它被称为罚款..我有一个会话范围的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>
这应该工作。尝试一下。
这似乎是一个更好的解决方案:) – 2014-11-21 09:25:50
感谢@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>
那就是如果你看到我的问题,我做了什么......创建了一个注销处理程序'myLogoutHandler',并且我正面临一个错误。 – 2014-11-21 10:02:10
在你的问题中,你可以简单地用默认的过滤器实现,用不同的属性覆盖默认的过滤器。我建议基于默认注销过滤器实现来实现您自己的LogoutFilter。你遇到的错误很奇怪,并提示一个命名空间问题,这可能是XML配置中的语法问题。你能否在你的问题中添加你的XML配置? //此外,你可以尝试davioooh的解决方案,它似乎更好。 – 2014-11-21 10:13:06
描述你还想要什么,我怀疑你需要一个自定义注销过滤器,因为它可能可以通过添加到其他LogoutHandler链中的LogoutHandler来完成。但是,由于你不知道你想达到什么(功能上),很难说。 – 2014-11-21 08:31:29
@ M.Deinum当会话即将销毁时,我实际上想对会话数据执行一些操作。希望现在明确 – 2014-11-21 09:50:00
然后,只需编写一个'ApplicationListener'来监听'HttpSessionDestroyedEvent's。还要将'HttpSessionEventPublisher'注册到您的web.xml中。通过这种方式,您还可以处理超时的会话,而不仅仅是定期注销。 – 2014-11-21 09:52:00