spring-security 在Spring Security中仅为少数路径禁用筛选器

kx1ctssn  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(228)

我如何获得一个过滤器来应用于根路径之外的每个请求,除了我想忽略的请求?下面是我的示例:
我有一个这样的Spring Security过滤器:

private static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().antMatcher("/**")
                    .addFilterBefore(new AuthenticationFilter(), BasicAuthenticationFilter.class);
        }

        @Override
        public void configure(WebSecurity web) {
            web.ignoring().requestMatchers(SecurityServletRequestMatchers.servletIgnoreAuthMatcher());
        }

    }

该过滤器填充一个CustomApiToken对象,该对象包含我们所有的头信息,并将其放入springsecuritycontext SecurityContextHolder.getContext().setAuthentication(token)中,以便轻松访问请求控制器上的令牌。
我正在尝试将springfox添加到项目中,这意味着我想禁用UI和api文档页面的过滤器。
我最初的尝试是在方法中添加一个子句:

@Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().antMatcher("/**")
                    .addFilterBefore(new AuthenticationFilter(), BasicAuthenticationFilter.class);

            http.requestMatcher(SecurityServletRequestMatchers.servletIgnoreAuthMatcher()).headers() //.servletIgnoreAuthMatchers has all the swagger urls also
                    .defaultsDisabled()
                    .disable()
                    .authorizeRequests()
                    .anyRequest().authenticated();
        }

然而,我发现,这只考虑了第二个条款,由于 Spring 安全只接受最后一个条款。
我试过:

@Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .antMatcher("/**")
                    .addFilterBefore(new AuthenticationFilter(), BasicAuthenticationFilter.class)
                    .requestMatcher(SecurityServletRequestMatchers.servletIgnoreAuthMatcher()).headers()
                    .defaultsDisabled()
                    .disable()
                    .authorizeRequests()
                    .anyRequest().authenticated();
        }

但这使得springfox url上的webfilter给我一个缺少身份验证令牌的错误。
我试着在这里和互联网上寻找,但没有一个例子给我一个可以接受的回应。

vfhzx4xs

vfhzx4xs1#

在自定义的AuthenticationFilter中,可以定义一个RequestMatcher,并在执行逻辑之前使用它,如下所示:

public class AuthenticationFilter extends OncePerRequestFilter {
    private final RequestMatcher ignoredPaths = new AntPathRequestMatcher("/swagger-ui");

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
        if (this.ignoredPaths.matches(request)) { 
             filterChain.doFilter(request, response);
             return;
        }

        // do your logic
        filterChain.doFilter(request, response);
    }
}
at0kjp5o

at0kjp5o2#

您可以在自定义过滤器中覆盖OncePerRequestFiltershouldNotFilter方法,以拆分您的 filternot_filter 逻辑,例如:

public class AuthenticationFilter extends OncePerRequestFilter {

    private final List<AntPathRequestMatcher> excludedMatchers;

    public AuthenticationFilter (List<AntPathRequestMatcher> excludedMatchers) {
        this.excludedMatchers = excludedMatchers;
    }

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

        // your filter logic here
        filterChain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        return excludedMatchers.stream()
                .anyMatch(matcher -> matcher.matches(request));
    }
}

默认情况下,此方法始终返回false,因此除非另外指定,否则过滤器将应用于任何请求。
请注意,AntPathRequestMatcher的构造函数也可以采用http方法,允许创建更具体的 not_filter 逻辑,如果您有多个具有相同路径和不同请求方法的端点,但希望只允许对特定端点的自由访问。

相关问题