init
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package space.luminic.budgerapp.configs
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
|
||||
import java.util.concurrent.Executor
|
||||
//
|
||||
//@Configuration
|
||||
//class AsyncConfig {
|
||||
// @Bean(name = ["taskExecutor"])
|
||||
// fun taskExecutor(): Executor {
|
||||
// val executor = ThreadPoolTaskExecutor()
|
||||
// executor.corePoolSize = 5
|
||||
// executor.maxPoolSize = 10
|
||||
// executor.setQueueCapacity(25)
|
||||
// executor.setThreadNamePrefix("Async-")
|
||||
// executor.initialize()
|
||||
// return executor
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,60 @@
|
||||
package space.luminic.budgerapp.configs
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.security.authentication.BadCredentialsException
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder
|
||||
import org.springframework.security.core.context.SecurityContext
|
||||
import org.springframework.security.core.context.SecurityContextImpl
|
||||
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.server.ServerWebExchange
|
||||
import org.springframework.web.server.WebFilterChain
|
||||
import reactor.core.publisher.Mono
|
||||
import space.luminic.budgerapp.services.AuthService
|
||||
|
||||
@Component
|
||||
class BearerTokenFilter(private val authService: AuthService) : SecurityContextServerWebExchangeWebFilter() {
|
||||
private val logger = LoggerFactory.getLogger(BearerTokenFilter::class.java)
|
||||
|
||||
override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
|
||||
val token = exchange.request.headers.getFirst(HttpHeaders.AUTHORIZATION)?.removePrefix("Bearer ")
|
||||
|
||||
if (exchange.request.path.value() == "/api/auth/login"){
|
||||
return chain.filter(exchange)
|
||||
}
|
||||
|
||||
return if (token != null) {
|
||||
authService.isTokenValid(token)
|
||||
.flatMap { userDetails ->
|
||||
val authorities = userDetails.roles.map { SimpleGrantedAuthority(it) }
|
||||
val securityContext = SecurityContextImpl(
|
||||
UsernamePasswordAuthenticationToken(
|
||||
userDetails.username, null, authorities
|
||||
)
|
||||
)
|
||||
chain.filter(exchange)
|
||||
.contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)))
|
||||
}
|
||||
.onErrorMap(AuthException::class.java) { ex ->
|
||||
BadCredentialsException(ex.message ?: "Unauthorized")
|
||||
}
|
||||
|
||||
} else {
|
||||
Mono.error(AuthException("Authorization token is missing"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
open class AuthException(msg: String) : RuntimeException(msg)
|
||||
@@ -0,0 +1,18 @@
|
||||
package space.luminic.budgerapp.configs
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.reactive.config.CorsRegistry
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer
|
||||
|
||||
@Configuration
|
||||
class CorsConfig : WebFluxConfigurer {
|
||||
|
||||
override fun addCorsMappings(registry: CorsRegistry) {
|
||||
registry.addMapping("/**") // Разрешить все пути
|
||||
.allowedOrigins("http://localhost:5173") // Разрешить домен localhost:5173
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") // Разрешить методы
|
||||
.allowedHeaders("*") // Разрешить все заголовки
|
||||
.allowCredentials(true) // Разрешить передачу cookies
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
//package space.luminic.budgerapp.configs
|
||||
//import org.springframework.http.HttpHeaders
|
||||
//import org.springframework.http.HttpStatus
|
||||
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
//import org.springframework.security.core.context.SecurityContextHolder
|
||||
//import org.springframework.stereotype.Component
|
||||
//import org.springframework.web.server.ServerWebExchange
|
||||
//import org.springframework.web.server.WebFilter
|
||||
//import org.springframework.web.server.WebFilterChain
|
||||
//import reactor.core.publisher.Mono
|
||||
//import space.luminic.budgerapp.services.AuthService
|
||||
//import space.luminic.budgerapp.services.TokenService
|
||||
//import space.luminic.budgerapp.utils.JWTUtil
|
||||
//
|
||||
//@Component
|
||||
//class JWTAuthFilter(
|
||||
// private val jwtUtil: JWTUtil,
|
||||
// private val authService: AuthService
|
||||
//) : WebFilter {
|
||||
//
|
||||
// override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
|
||||
// val authHeader = exchange.request.headers.getFirst(HttpHeaders.AUTHORIZATION)
|
||||
//
|
||||
// if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||
// val token = authHeader.substring(7)
|
||||
// return Mono.just(token)
|
||||
// .filter { authService.isTokenValid(it) }
|
||||
// .flatMap { validToken ->
|
||||
// val username = jwtUtil.validateToken(validToken)
|
||||
// if (username != null) {
|
||||
// val auth = UsernamePasswordAuthenticationToken(username, null, emptyList())
|
||||
// SecurityContextHolder.getContext().authentication = auth
|
||||
// }
|
||||
// chain.filter(exchange)
|
||||
// }
|
||||
// .onErrorResume {
|
||||
// exchange.response.statusCode = HttpStatus.UNAUTHORIZED
|
||||
// exchange.response.setComplete()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return chain.filter(exchange)
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,33 @@
|
||||
//package space.luminic.budgerapp.configs
|
||||
//
|
||||
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
//import org.springframework.security.authentication.ReactiveAuthenticationManager
|
||||
//import org.springframework.security.core.Authentication
|
||||
//import org.springframework.security.core.userdetails.ReactiveUserDetailsService
|
||||
//import org.springframework.security.crypto.password.PasswordEncoder
|
||||
//import org.springframework.stereotype.Component
|
||||
//import reactor.core.publisher.Mono
|
||||
//import space.luminic.budgerapp.services.CustomReactiveUserDetailsService
|
||||
//import space.luminic.budgerapp.services.TokenService
|
||||
//import space.luminic.budgerapp.utils.JWTUtil
|
||||
//
|
||||
//@Component
|
||||
//class JWTReactiveAuthenticationManager(
|
||||
// private val passwordEncoder: PasswordEncoder,
|
||||
// private val userDetailsService: CustomReactiveUserDetailsService
|
||||
//) : ReactiveAuthenticationManager {
|
||||
//
|
||||
//
|
||||
// override fun authenticate(authentication: Authentication): Mono<Authentication> {
|
||||
// val username = authentication.principal as String
|
||||
// val password = authentication.credentials as String
|
||||
//
|
||||
// return userDetailsService.findByUsername(username)
|
||||
// .filter { userDetails -> password == passwordEncoder.encode(userDetails.password) } // Пример проверки пароля
|
||||
// .map { userDetails ->
|
||||
// UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
@@ -0,0 +1,62 @@
|
||||
package space.luminic.budgerapp.configs
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.security.config.web.server.SecurityWebFiltersOrder
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain
|
||||
import space.luminic.budgerapp.controllers.CustomAuthenticationEntryPoint
|
||||
|
||||
|
||||
import space.luminic.budgerapp.services.AuthService
|
||||
|
||||
@Configuration
|
||||
class SecurityConfig(
|
||||
private val authService: AuthService
|
||||
) {
|
||||
@Bean
|
||||
fun securityWebFilterChain(
|
||||
http: ServerHttpSecurity,
|
||||
bearerTokenFilter: BearerTokenFilter,
|
||||
customAuthenticationEntryPoint: CustomAuthenticationEntryPoint
|
||||
): SecurityWebFilterChain {
|
||||
return http
|
||||
.csrf { it.disable() }
|
||||
.cors { it.configurationSource(corsConfigurationSource()) }
|
||||
|
||||
.logout { it.disable() }
|
||||
.authorizeExchange {
|
||||
it.pathMatchers(HttpMethod.POST, "/auth/login").permitAll()
|
||||
it.pathMatchers("/actuator/**").permitAll()
|
||||
it.anyExchange().authenticated()
|
||||
}
|
||||
.addFilterAt(
|
||||
bearerTokenFilter,
|
||||
SecurityWebFiltersOrder.AUTHENTICATION
|
||||
) // BearerTokenFilter только для authenticated
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
fun passwordEncoder(): PasswordEncoder {
|
||||
return BCryptPasswordEncoder()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun corsConfigurationSource(): org.springframework.web.cors.reactive.CorsConfigurationSource {
|
||||
val corsConfig = org.springframework.web.cors.CorsConfiguration()
|
||||
corsConfig.allowedOrigins =
|
||||
listOf("https://luminic.space", "http://localhost:5173") // Ваши разрешённые источники
|
||||
corsConfig.allowedMethods = listOf("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")
|
||||
corsConfig.allowedHeaders = listOf("*")
|
||||
corsConfig.allowCredentials = true
|
||||
|
||||
val source = org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource()
|
||||
source.registerCorsConfiguration("/**", corsConfig)
|
||||
return source
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user