首页 > 解决方案 > 在 Spring Boot 中排除某些 URL 的自定义过滤器

问题描述

我有一个使用 OAuth 身份验证的 Spring Boot 应用程序。除了身份验证之外,我还需要授权用户才能访问系统。我创建了一个自定义过滤器来授权用户。我只想在BasicAuthenticationFilter. 如果BasicAuthenticationFilter没有运行,那么我的过滤器也不应该运行。

授权过滤器.java

@Component
public class AuthorizationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        boolean isValidUser = true;
        // we get the authenticated user from the context
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String id = (authentication == null)? "" : authentication.getName();

        ..
        // code to get the user data from database using 'id' and set isValidUser flag
        ..
        if(isValidUser) {
            filterChain.doFilter(request, response);
        }
        else {
            ...
            // handle UNAUTHORIZED
            ...
        }
    }
}

安全配置.java

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity security) throws Exception {

        security.requestMatchers()
                .antMatchers("/actuator/health")
                .and()
                .authorizeRequests()
                .antMatchers("/actuator/health").permitAll()
                .and()
                .csrf().disable();

        security.cors();

        // Custom filter to validate if user is authorized and active to access the system
        security.addFilterAfter(new AuthorizationFilter(), BasicAuthenticationFilter.class);
    }
}

问题:

  1. 即使我已允许“/actuator/health”端点,我的自定义过滤器仍会针对该端点运行。如何排除我的过滤器在“/actuator/health”上运行?

  2. 完美的解决方案是仅在运行时运行我的过滤器BasicAuthenticationFilter。这可能吗?如何?

标签: spring-bootspring-securityoauthspring-security-oauth2servlet-filters

解决方案


AFAIK,这类问题的最佳解决方案是创建一个新的过滤器链。在您的情况下,将有一个过滤器链用于需要身份验证的端点,而另一个过滤器链用于打开的端点(不需要任何身份验证)。这是未受保护端点的示例过滤器链:

<bean id="openFilterChain" class="org.springframework.security.web.DefaultSecurityFilterChain">
    <description>Pass the list of filters that you want to invoke for the given request matcher.</description>
    <constructor-arg index="0" ref="infoRequestMatcher"/>
    <constructor-arg index="1">
        <list>
            <ref bean="exceptionTranslationFilter"/>
        </list>
    </constructor-arg>
</bean>

<bean id="infoRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
    <description>
        Pass the request matcher that matches all you unprotected endpoints.
    </description>
    <constructor-arg index="0" value="/actuator/health"/>
</bean>

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <description>
        Register your custom filter chain here.
    </description>
    <constructor-arg>
        <list>
            <ref bean="openFilterChain"/>
            <ref bean="otherSecurityFilterChain"/>
        </list>
    </constructor-arg>
</bean>

推荐阅读