Spring boot 3 和 Spring security 预授权

问题描述 投票:0回答:1

我通常会尽量避免使用 spring auth,因为它通常会注入许多极难禁用的默认值。但现在我需要使用 JWT 令牌。因此,我创建了一个安全配置,但发生了预身份验证失败,我无法弄清楚如何禁用:

Pre-authenticated entry point called. Rejecting access
任何人都可以与我分享如何在 boot 3 应用程序中禁用预身份验证吗?以下是我当前的配置

@Bean
@Throws(Exception::class)
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
    return http.csrf { it.disable() }
        .authorizeHttpRequests { it.anyRequest().authenticated() }
        .sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }
        .authenticationProvider(authenticationProvider())
        .build()
}

@Bean
fun authenticationProvider(): AuthenticationProvider {
    val authenticationProvider = JwtAuthenticationProvider(jwtDecoder())
    return authenticationProvider
}

@Bean
fun jwtDecoder(): JwtDecoder {
    return NimbusJwtDecoder.withPublicKey(rsaProperties.publicKey).build()
}

@Bean
fun jwtEncoder(): JwtEncoder {
    val jwk: JWK =
        RSAKey.Builder(rsaProperties.publicKey).privateKey(rsaProperties.privateKey).build()

    val jwks: JWKSource<SecurityContext> = ImmutableJWKSet(JWKSet(jwk))
    return NimbusJwtEncoder(jwks)
}

Spring Security Web 的调试日志:

2024-02-14T13:58:20.238-08:00 DEBUG 5308 --- [tp1468039653-29] o.s.security.web.FilterChainProxy: Securing POST /v1/ds/123456789/register
2024-02-14T13:58:20.239-08:00 DEBUG 5308 --- [tp1468039653-29] o.s.s.w.a.AnonymousAuthenticationFilter: Set SecurityContextHolder to anonymous SecurityContext
2024-02-14T13:58:20.239-08:00 DEBUG 5308 --- [tp1468039653-29] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-02-14T13:58:20.243-08:00 DEBUG 5308 --- [tp1468039653-29] o.s.security.web.FilterChainProxy        : Securing POST /error
2024-02-14T13:58:20.244-08:00 DEBUG 5308 --- [tp1468039653-29] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-02-14T13:58:20.244-08:00 DEBUG 5308 --- [tp1468039653-29] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
spring-boot spring-security jwt
1个回答
0
投票

所以问题是我相信因为 AuthenticationProvider 是一个 JwtAuthenticationProvider,jwt 安全过滤的核心将由该身份验证提供程序“提供”,但事实并非如此。我更新了我的安全配置以拥有 jwtFilter 和身份验证提供程序,现在它正在工作。为了解决一些循环引用,上述问题中的编码器/解码 bean 已移至单独的 bean 配置类。

@Configuration
@EnableWebSecurity
class SecurityConfig(
  private val jwtDecoder: JwtDecoder,
  private val jwtfilter: JwtAuthFilter
) {

  @Bean
  @Throws(Exception::class)
  fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
    return http.csrf { it.disable() }
        .authorizeHttpRequests { it.anyRequest().authenticated() }
        .sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }
        .authenticationProvider(authenticationProvider())
        .addFilterBefore(jwtfilter, UsernamePasswordAuthenticationFilter::class.java)
        .build()
  }

  @Bean
  fun authenticationProvider(): AuthenticationProvider {
    val authenticationProvider = JwtAuthenticationProvider(jwtDecoder)
    return authenticationProvider
  }
}

对于那些想要它的人来说,这里也是过滤器,过滤器中引用的 jwtService 只是使用 NimbusJwtDecoder 和 NimbusJwtEncoder 来完成所有繁重的工作:

@Component
class JwtAuthFilter(private val jwtService: JwtService) : OncePerRequestFilter() {
val log: Logger = LoggerFactory.getLogger(javaClass)

  override fun doFilterInternal(
    request: HttpServletRequest,
    response: HttpServletResponse,
    filterChain: FilterChain) {
    val authHeader: String = request.getHeader("Authorization") ?: throw InvalidJwtException("No JWT Header provided")
    var token: String? = null
    var cachingRequest: ContentCachingRequestWrapper? = null
    if (authHeader != null && authHeader.startsWith("Bearer ")) {
        token = authHeader.removePrefix("Bearer").trim()
    }
    val contentType = request.contentType
    if (contentType == null || !contentType.contains("multipart/form-data")) {
        // Wrap the request, so we can read the payload multiple times
        cachingRequest = ContentCachingRequestWrapper(request)
    }
    val payload = cachingRequest?.reader?.readText() ?: ""

    if (SecurityContextHolder.getContext().authentication == null) {
        log.trace("Validating JWT token")
        jwtService.validateToken(token!!, payload)?.let {
            val authenticationToken = JwtAuthenticationToken(it, listOf(SimpleGrantedAuthority("ROLE_USER")))
            SecurityContextHolder.getContext().authentication = authenticationToken
        } ?: throw InvalidJwtException("Invalid JWT token provided")
    }
    filterChain.doFilter(request, response)
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.