You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让OncePerRequestFilter过滤器跳过无需JWT验证的URL

解决方案

有两种常见方式可以让JwtFilter跳过无需验证的URL,以下是具体实现:

方案一:在JwtFilter内部添加路径忽略逻辑

直接在过滤器中判断请求路径是否属于无需验证的范围,若是则直接放行,不执行JWT验证逻辑:

import org.springframework.util.AntPathMatcher
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.springframework.web.filter.OncePerRequestFilter
import io.jsonwebtoken.Jwts
import java.util.Date
import org.springframework.http.HttpHeaders

class JwtFilter(
    private val securityProperties: SecurityProperties
) : OncePerRequestFilter() {

    companion object {
        const val PREFIX = "Bearer "
        // 定义需要忽略的URL模式
        private val IGNORED_PATHS = listOf("/api/auth/**")
        private val PATH_MATCHER = AntPathMatcher()
    }

    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        // 检查当前请求是否匹配忽略路径,匹配则直接放行
        val requestUri = request.requestURI
        if (IGNORED_PATHS.any { PATH_MATCHER.match(it, requestUri) }) {
            filterChain.doFilter(request, response)
            return
        }

        val token = resolvedToken(request)
        if (token.isEmpty())
            throw InvalidTokenException
        try {
            val claims = Jwts.parser()
                .setSigningKey(securityProperties.key)
                .parseClaimsJws(token)

            val jwtBody = claims.body // 修正原代码笔误:jwtDody -> jwtBody

            val expiration = jwtBody.expiration

            if (expiration.before(Date())) {
                throw ExpiredTokenException
            }
            filterChain.doFilter(request, response)
        } catch (e: Exception) {
            throw InvalidTokenException
        }
    }


    private fun resolvedToken(request: HttpServletRequest): String {
        val bearerToken: String? = request.getHeader(HttpHeaders.AUTHORIZATION)
        bearerToken?.let {
            if (bearerToken.startsWith(PREFIX)) {
                return bearerToken.substring(PREFIX.length)
            }
        }
        return ""
    }
}

方案二:在SecurityConfig中限定过滤器的拦截范围

通过Spring Security的配置,让JwtFilter仅对需要验证的URL生效,自然跳过无需JWT的路径:

import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import org.springframework.security.web.util.matcher.NegatedRequestMatcher
import org.springframework.security.web.util.matcher.RequestMatcher

@Configuration
@EnableWebSecurity
class SecurityConfig(
    val securityProperties: SecurityProperties
) {
    @Bean
    protected fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        // 定义需要排除的请求匹配器
        val ignoredRequestMatcher: RequestMatcher = NegatedRequestMatcher(AntPathRequestMatcher("/api/auth/**"))

        http
            .csrf().disable()
            .httpBasic().disable()
            .cors()
            .and()

            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()

            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .anyRequest().authenticated() // 补充其他路径需认证的规则
            .and()

            // 仅对非/api/auth/**的请求应用JwtFilter
            .addFilterBefore(JwtFilter(securityProperties), UsernamePasswordAuthenticationFilter::class.java)
            .requestMatcher(ignoredRequestMatcher)

        return http.build()
    }


    @Bean
    protected fun passwordEncoder() = BCryptPasswordEncoder()
}

两种方案对比

  • 方案一:过滤器内部自主控制忽略路径,无需修改Security配置,适合忽略路径较少、规则简单的场景。
  • 方案二:通过Security配置统一管理拦截范围,逻辑更清晰,适合复杂的路径匹配规则,符合Spring Security的配置习惯。

内容的提问来源于stack exchange,提问作者HamTory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:43:14