Spring安全自定义过滤器多次调用

时间:2015-03-26 17:57:51

标签: spring spring-security servlet-filters

我有六次自定义注销过滤器。我尝试访问应用程序时两次,当我输入用户名/密码并点击“登录”时再两次,当我点击“退出”时再次两次。

我做错了什么?

配置:

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN_FUNCTIONS')" />      
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

    <form-login login-page="/login"
        authentication-success-handler-ref="customAuthenticationSuccessHandlerBean"
        authentication-failure-handler-ref="customAuthenticationFailureHandlerBean" />
    <logout invalidate-session="true" success-handler-ref="logoutHandlerBean" />
    <session-management session-fixation-protection="migrateSession">
        <concurrency-control max-sessions="1"
            expired-url="/login_sessionexpired" />
    </session-management>

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

<beans:bean id="customLogoutFilter" class="com.hurontg.libms.security.CustomLogoutFilter" />

过滤器:

public class CustomLogoutFilter extends OncePerRequestFilter {
/**
 * 
 */
private XLogger logger = XLoggerFactory
        .getXLogger(CustomLogoutFilter.class.getName());

@Override
protected void doFilterInternal(HttpServletRequest req,
        HttpServletResponse res, FilterChain chain)
        throws ServletException, IOException {

    logger.error("========================================================================================");
    logger.error("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Custom Logout Filter $$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
    logger.error("========================================================================================");

    chain.doFilter(req, res);
}

}

Spring版本:4.1.1 Spring安全:3.2.5

4 个答案:

答案 0 :(得分:29)

如果您使用的是Spring Boot,则上下文中的任何GenericFilterBean(OncePerRequestFilter为1)都将自动添加到过滤器链中。这意味着您上面的配置将包括相同的过滤器两次。

最简单的解决方法是在上下文中定义FilterRegistrationBean并禁用它:

<beans:bean id="customLogoutFilterRegistration" class="org.springframework.boot.context.embedded.FilterRegistrationBean">
    <beans:property name="filter" ref="customLogoutFilter"/>
    <beans:property name="enabled" value="false"/>
</beans:bean>

答案 1 :(得分:4)

可能会调用其他正在请求的URL。例如,如果您有任何css,javascript,页面上加载的图像,将为每个图像调用它们。尝试添加一个显示当前请求信息的日志记录语句,以确定是否是这种情况。例如,

logger.error("URL = " + req.getRequestURL());

答案 2 :(得分:1)

只需分享我的案例即可:(

我没有在AuthenticationProvider中设置authentication.setAuthenticated(true)

因此,AbstractPreAuthenticatedProcessingFilter曾经叫过authenticate,然后AbstractSecurityInterceptor也叫了authenticateIfNeeded

答案 3 :(得分:0)

Spring Security大约有12个过滤器,其中一些尝试检查用户是否已通过身份验证。例如,有一个名为AnonymousAuthenticationFilter的过滤器。

如果要提供身份验证提供程序,并且已经对请求进行了一次身份验证,则应在安全上下文中设置身份验证对象。

SecurityContextHolder.getContext().setAuthentication(authentication)

在示例中,AnonymousAuthenticationFilter尝试从安全上下文中获取身份验证。如果找不到,它将再次拨打电话。