Files
test/src/main/kotlin/com/auth/config/WebSecurityConfig.kt
dmitriy.churmeev 85b33f9cb9
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix security configuration
2026-03-29 15:07:56 +03:00

105 lines
4.6 KiB
Kotlin

package com.auth.config
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter
import org.springframework.security.web.SecurityFilterChain
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(
prePostEnabled = true, // ← явно включаем
securedEnabled = true // ← опционально
)
class WebSecurityConfig () {
private val logger = org.slf4j.LoggerFactory.getLogger(WebSecurityConfig::class.java)
@Bean
@Throws(Exception::class)
fun filterChain(http: HttpSecurity): SecurityFilterChain? {
http.authorizeHttpRequests(Customizer { auth ->
auth.requestMatchers("/public/**", "/health", "/info").permitAll()
//auth.anyRequest().permitAll()
auth.anyRequest().authenticated()
})
.oauth2ResourceServer(Customizer { oauth2 ->
// oauth2!!.jwt(Customizer.withDefaults())
// добавляем конвертер для извлечения ролей
oauth2.jwt { jwt ->
jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())
}
}) // проверка JWT токен
.sessionManagement(Customizer { session: SessionManagementConfigurer<HttpSecurity?>? ->
session!!.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}) // без сессий
.csrf(Customizer { csrf: CsrfConfigurer<HttpSecurity?>? -> csrf!!.disable() }) // отключаем CSRF для API
return http.build()
}
private fun jwtAuthenticationConverter(): JwtAuthenticationConverter {
val converter = JwtAuthenticationConverter()
converter.setJwtGrantedAuthoritiesConverter { jwt ->
val roles = mutableSetOf<SimpleGrantedAuthority>()
// Извлекаем роли из resource_access.test_client.roles
val resourceAccess = jwt.claims["resource_access"] as? Map<*, *>
logger.info("Roles! "+resourceAccess)
val clientAccess = resourceAccess?.get("test_client") as? Map<*, *>
val clientRoles = clientAccess?.get("roles") as? List<*>
clientRoles?.forEach { role ->
roles.add(SimpleGrantedAuthority("ROLE_$role"))
}
// Альтернативно: можно также читать из realm_access.roles
val realmAccess = jwt.claims["realm_access"] as? Map<*, *>
val realmRoles = realmAccess?.get("roles") as? List<*>
realmRoles?.forEach { role ->
roles.add(SimpleGrantedAuthority("ROLE_$role"))
}
roles.toList()
}
return converter
}
// // Конвертер JWT Authentication (извлекает роли из токена)
// private fun jwtAuthenticationConverter(): JwtAuthenticationConverter {
// val converter = JwtAuthenticationConverter()
//
// // Извлекаем роли из поля resource_access.test_client.roles
// val authoritiesExtractor = JwtGrantedAuthoritiesConverter()
// authoritiesExtractor.setAuthoritiesClaimName("resource_access.test_client.roles") // где лежат роли
// authoritiesExtractor.setAuthorityPrefix("ROLE_") // добавляем префикс ROLE_
//
// converter.setJwtGrantedAuthoritiesConverter(authoritiesExtractor)
//
//// // Дополнительно: проверяем, что роли не пустые
//// converter.setJwtGrantedAuthoritiesConverter { jwt ->
//// val authorities = authoritiesExtractor.convert(jwt)
//// if (authorities.isEmpty()) {
//// throw IllegalArgumentException("User has no roles assigned in token")
//// }
//// authorities
//// }
//
// return converter
// }
}