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

Spring Security 5.7如何正确注册OncePerRequestFilter校验Token

Spring Security JWT 权限配置问题

需求说明

我正在通过提供登录、刷新端点的AuthController实现简易Web服务权限管控,规则如下:

  • /auth/** 路径开放匿名访问
  • 其余所有API仅在携带有效Token时才可访问

目前认证端点本身逻辑可正常运行,但安全配置存在异常:将JwtTokenFilter添加到安全配置后,向auth/login路径发送POST请求时出现连接拒绝错误;同时将JwtTokenFilter声明为Bean后,无法断点调试进入filterChain执行逻辑,初步判断是过滤器的实现或注册方式存在错误。

初始实现代码

JwtTokenFilter 代码

class JwtTokenFilter() : OncePerRequestFilter() {

    @Autowired
    private lateinit var jwtTokenService: JwtTokenService

    @Autowired
    private lateinit var refreshTokenService: RefreshTokenService

    @Autowired
    private lateinit var userDetailService: UserDetailService

    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        val jwt = jwtTokenService.getTokenFromAuthHeader(request)
        jwt?.let { token ->
            try {
                val claims = jwtTokenService.getClaimsFromToken(token)
                val userDetails = userDetailService.loadUserByUsername(claims.subject)
                val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
                authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
                SecurityContextHolder.getContext().authentication = authentication
                refreshTokenService.updateRefreshToken(claims.subject)
            } catch (ex: Exception) {
                logger.warn("JWT-Token <$token> invalid token")
            }
        }
        logger.trace("API request to <${request.requestURI}> with token <${!jwt.isNullOrEmpty()}>")

        filterChain.doFilter(request, response)
    }
}

初始WebSecurityConfig配置代码

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
class WebSecurityConfig() {

    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http.authorizeHttpRequests()
            .antMatchers("/auth/**").permitAll()
            .anyRequest().authenticated()
        http.csrf().disable()
        http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter::class.java)

        return http.build()
    }

    @Bean
    fun jwtTokenFilter(): JwtTokenFilter {
        return JwtTokenFilter()
    }
    @Bean
    fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager? {
        return authenticationConfiguration.authenticationManager
    }

    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return BCryptPasswordEncoder()
    }
}

调整后的WebSecurityConfig配置

针对上述问题我更新了WebSecurityConfig配置,改为构造器注入依赖、新增无状态会话配置,调整后代码如下:

@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
@EnableWebSecurity(debug = true)
@Configuration
class WebSecurityConfig(
    private val jwtTokenService: JwtTokenService,
    private val refreshTokenService: RefreshTokenService,
    private val userDetailService: UserDetailService
) {

    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http
            .csrf().disable()

        http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

        http.authorizeHttpRequests()
            .antMatchers("/auth/**").permitAll()

        http.authorizeHttpRequests()
            .anyRequest().authenticated()

        //http.apply(MyCustomDsl.customDsl(jwtTokenService, userDetailService, refreshTokenService))
        http.addFilterBefore(JwtTokenFilter(jwtTokenService, userDetailService, refreshTokenService), UsernamePasswordAuthenticationFilter::class.java)
        return http.build()
    }


    @Bean
    fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager? {
        return authenticationConfiguration.authenticationManager
    }

    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return BCryptPasswordEncoder()
    }

/*    class MyCustomDsl(
        private val jwtTokenService: JwtTokenService,
        private val userDetailService: UserDetailService,
        private val refreshTokenService: RefreshTokenService,
        ) : AbstractHttpConfigurer<MyCustomDsl, HttpSecurity>() {

        companion object {
            fun customDsl(jwtTokenService: JwtTokenService,userDetailService: UserDetailService, refreshTokenService: RefreshTokenService): MyCustomDsl {
                return MyCustomDsl(jwtTokenService, userDetailService, refreshTokenService)
            }
        }

        override fun configure(http: HttpSecurity) {
            http.addFilterBefore(JwtTokenFilter(jwtTokenService, userDetailService, refreshTokenService), UsernamePasswordAuthenticationFilter::class.java)
        }
    }*/
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:54:29