java - 即使在允许的 url 上也可以访问 Jwt 过滤器

标签 java spring spring-boot spring-security jwt

我正在开发一个 Spring Boot 应用程序,我在其中定义了要执行的过滤器来管理获取和验证 token 。所以在我的 Web 安全类配置中,我设法做到了:

@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // we don't need CSRF because our token is invulnerable
                .csrf().disable()

                // don't create session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

                .authorizeRequests()
                // .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

                // allow anonymous resource requests
                .antMatchers(HttpMethod.GET, "/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
                .antMatchers("/auth/**").permitAll()
                .antMatchers("/places/public").permitAll()

                .anyRequest().authenticated();

        // Custom JWT based security filter
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);

        // disable page caching
        httpSecurity.headers().cacheControl();
    }

authenticationTokenFilterBean 是一个用 @Bean 注释的方法,它返回我的过滤器的一个实例:
public class JwtFilter extends OncePerRequestFilter{

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtService jwtService;

    @Value("${jwt.header}")
    private String authorizationHeader;

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

        String token = httpServletRequest.getHeader(authorizationHeader);

        String username = jwtService.getUsernameFromToken(token);

        if(username!=null && SecurityContextHolder.getContext().getAuthentication() ==null){
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            if(jwtService.isTokenValid(token, userDetails)){
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }

        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

}

由于我正在扩展OncePerRequestFilter,因此每个请求仅调用此过滤器一次,而GenericFilter 则不是这种情况,它需要由servlet 执行一次,另一次使用Spring 安全性执行。

我遇到的问题是,即使我使用 permitAll() 方法允许它们,我的配置类中描述的 ant 匹配器也会被过滤器拦截,我尝试覆盖 WebSecurityConfigurerAdapter 中的 configure(WebSecurity web) 方法并忽略它们,但仍然没有用。

如何配置 Spring security 以跳过这些请求的过滤器?我已经检查过这个问题 Spring Security JWT Filter applies on all requests但它没有解决方案。

谢谢

最佳答案

仍然在过滤器内部处理,但方法更清洁。
您可以覆盖 shouldNotFilter(HttpServletRequest request) OncePerRequestFilter的方法并根据 URL 模式返回 true 以跳过过滤。

private static List<String> skipFilterUrls = Arrays.asList("/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js");

@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {

  return skipFilterUrls.stream().anyMatch(url -> new AntPathRequestMatcher(url).matches(request));
}

关于java - 即使在允许的 url 上也可以访问 Jwt 过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46683298/

相关文章:

java - 你在哪里定义spring bean配置文件

Java 11 模块信息 : how to register an annotation processor

java - Jackson是否支持JsonPath注解

java - 属性文件的spring boot外部配置

java - 如何在没有 ObjectId 的情况下将 Mongo 与 Spring Data 一起使用

java - xStream 问题 - 如何反序列化多个对象

java - 根据主体tomcat重定向请求

java - Spring Security配置问题

java - Spring MVC + Security with Java Configuration

java - 如何将 querydsl-mongodb 添加到 Spring Boot Gradle 5.6.1 项目