简体   繁体   English

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

[英]Spring security custom filter called multiple times

I have a custom logout filter called six times.我有一个名为六次的自定义注销过滤器。 Twice as soon I try to access the application, twice when I enter username/password and click on 'Login' and then twice again when I click on 'logout'.我尝试访问应用程序后两次,当我输入用户名/密码并单击“登录”时两次,然后当我单击“注销”时再次两次。

What am I doing wrong?我究竟做错了什么?

Configuration:配置:

<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" />

The filter:过滤器:

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 version: 4.1.1 Spring security: 3.2.5 Spring 版本:4.1.1 Spring 安全性:3.2.5

If you are using Spring Boot, any GenericFilterBean (OncePerRequestFilter is one) in the context will be automatically added to the filter chain.如果您在使用Spring启动,任何GenericFilterBean (OncePerRequestFilter就是其中之一)的背景下,将被自动添加到过滤器链。 Meaning the configuration you have above will include the same filter twice.这意味着您上面的配置将包含两次相同的过滤器。

The easiest workaround for this is to define a FilterRegistrationBean in the context, and have it disabled:最简单的解决方法是在上下文中定义一个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>

EDIT (11/3/2020):编辑(11/3/2020):

For anyone working in SpringBoot and wanting to register the bean using annotations.对于在 SpringBoot 中工作并希望使用注释注册 bean 的任何人。 Add the following code in the Spring Boot app initializer file (one with @SpringBootApplication annotation):在 Spring Boot 应用程序初始值设定项文件(带有 @SpringBootApplication 注释的一个)中添加以下代码:

@Bean
public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    registrationBean.setFilter(new YourCustomFilterClassName());
    registrationBean.setEnabled(false);
    return registrationBean;
}

It is likely being called for other URLs that are being requested.它可能会被请求的其他 URL 调用。 For example, if you have any css, javascript, images that are loaded on the page it will be called for each of those.例如,如果您有任何 css、javascript、图像加载到页面上,它将为每个图像调用。 Try adding a logging statement that displays the current request information to find out if that is the case.尝试添加一个显示当前请求信息的日志语句,以确定是否是这种情况。 For example,例如,

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

Just sharing my case :(只是分享我的案例:(

I wasn't setting authentication.setAuthenticated(true) in the AuthenticationProvider.我没有在 AuthenticationProvider 中设置authentication.setAuthenticated(true)

Hence, AbstractPreAuthenticatedProcessingFilter called authenticate once, then AbstractSecurityInterceptor was also calling authenticateIfNeeded .因此, AbstractPreAuthenticatedProcessingFilter调用了一次authenticate ,然后AbstractSecurityInterceptor也调用了authenticateIfNeeded

Spring security has around 12 filters and a few of them try to check if the user is authenticated. Spring security 有大约 12 个过滤器,其中一些会尝试检查用户是否通过身份验证。 For example, there is a filter called AnonymousAuthenticationFilter.例如,有一个名为 AnonymousAuthenticationFilter 的过滤器。

If you are providing your authentication provider and you have authenticated the request once, you should set the authentication object in the security context.如果您提供身份验证提供程序并且已对请求进行一次身份验证,则应在安全上下文中设置身份验证对象。

SecurityContextHolder.getContext().setAuthentication(authentication)

In the example, AnonymousAuthenticationFilter tries to get the authentication from the security context.在示例中, AnonymousAuthenticationFilter 尝试从安全上下文中获取身份验证。 If not found, it will once again make a call again.如果没有找到,它会再次拨打电话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM