### fix: behebe CORS-Probleme und Stabilitätsfehler
All checks were successful
All checks were successful
- **MailController:** Erweitere `@CrossOrigin`-Headers und Methoden für Preflight-Checks. - **GlobalSecurityConfig:** Reaktiviere CORS und füge explizite `CorsConfigurationSource` hinzu. - **Tests:** Fix für `NoSuchBeanDefinitionException` bei Integrationstests. - **UI:** Aktualisiere Versionsmarker auf `v2026-04-23.15 - CORS STABILITY`.
This commit is contained in:
parent
af02e14f2d
commit
3244efd5e0
|
|
@ -7,10 +7,16 @@ 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.configuration.EnableWebSecurity
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy
|
import org.springframework.security.config.http.SessionCreationPolicy
|
||||||
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator
|
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator
|
||||||
import org.springframework.security.oauth2.jwt.*
|
import org.springframework.security.oauth2.jwt.Jwt
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtDecoder
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtTimestampValidator
|
||||||
|
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
|
||||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter
|
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter
|
||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||||
|
import org.springframework.web.cors.CorsConfiguration
|
||||||
|
import org.springframework.web.cors.CorsConfigurationSource
|
||||||
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
|
@ -21,10 +27,8 @@ class GlobalSecurityConfig {
|
||||||
fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http
|
http
|
||||||
.csrf { it.disable() } // CSRF nicht nötig für Stateless REST APIs
|
.csrf { it.disable() } // CSRF nicht nötig für Stateless REST APIs
|
||||||
// WICHTIG: CORS explizit deaktivieren!
|
// WICHTIG: CORS wieder aktivieren für Plan-B (Direktzugriff ohne Gateway möglich)
|
||||||
// Das API-Gateway kümmert sich um CORS. Die Microservices dürfen KEINE
|
.cors { it.configurationSource(corsConfigurationSource()) }
|
||||||
// Access-Control-Allow-Origin Header setzen, sonst haben wir doppelte Header beim Client.
|
|
||||||
.cors { it.disable() }
|
|
||||||
.sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }
|
.sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }
|
||||||
.addFilterBefore(DeviceSecurityFilter(), UsernamePasswordAuthenticationFilter::class.java)
|
.addFilterBefore(DeviceSecurityFilter(), UsernamePasswordAuthenticationFilter::class.java)
|
||||||
.authorizeHttpRequests { auth ->
|
.authorizeHttpRequests { auth ->
|
||||||
|
|
@ -71,4 +75,22 @@ class GlobalSecurityConfig {
|
||||||
converter.setJwtGrantedAuthoritiesConverter(KeycloakRoleConverter())
|
converter.setJwtGrantedAuthoritiesConverter(KeycloakRoleConverter())
|
||||||
return converter
|
return converter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
fun corsConfigurationSource(): CorsConfigurationSource {
|
||||||
|
val configuration = CorsConfiguration()
|
||||||
|
configuration.allowedOrigins = listOf(
|
||||||
|
"https://app.mo-code.at",
|
||||||
|
"https://api.mo-code.at",
|
||||||
|
"http://localhost:8080",
|
||||||
|
"http://localhost:8083",
|
||||||
|
"http://localhost:4000"
|
||||||
|
)
|
||||||
|
configuration.allowedMethods = listOf("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||||
|
configuration.allowedHeaders = listOf("*")
|
||||||
|
configuration.allowCredentials = true
|
||||||
|
val source = UrlBasedCorsConfigurationSource()
|
||||||
|
source.registerCorsConfiguration("/**", configuration)
|
||||||
|
return source
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,11 @@ data class NennungRequest(
|
||||||
@OptIn(ExperimentalUuidApi::class)
|
@OptIn(ExperimentalUuidApi::class)
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/mail")
|
@RequestMapping("/api/mail")
|
||||||
@CrossOrigin(origins = ["http://localhost:8080", "https://nennung.mo-code.at", "https://app.mo-code.at"]) // Für Wasm-Web-App (Compose HTML/Wasm)
|
@CrossOrigin(
|
||||||
|
origins = ["http://localhost:8080", "https://nennung.mo-code.at", "https://app.mo-code.at", "https://api.mo-code.at"],
|
||||||
|
allowedHeaders = ["*"],
|
||||||
|
methods = [RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS]
|
||||||
|
) // Für Wasm-Web-App (Compose HTML/Wasm)
|
||||||
class MailController(
|
class MailController(
|
||||||
private val nennungRepository: NennungRepository,
|
private val nennungRepository: NennungRepository,
|
||||||
private val mailSender: JavaMailSender
|
private val mailSender: JavaMailSender
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,18 @@ Die "Hallo Du!" Test-UI wurde durch produktive, fachlich korrekte Formulare erse
|
||||||
- `PlatformConfig.wasmJs.kt`: Alle Logiken zur Erkennung von URLs wurden temporär deaktiviert. Die Funktionen `resolveMailServiceUrl()` und `resolveApiBaseUrl()` geben nun **zwingend** `https://api.mo-code.at` zurück.
|
- `PlatformConfig.wasmJs.kt`: Alle Logiken zur Erkennung von URLs wurden temporär deaktiviert. Die Funktionen `resolveMailServiceUrl()` und `resolveApiBaseUrl()` geben nun **zwingend** `https://api.mo-code.at` zurück.
|
||||||
- Dies umgeht jegliches Caching von `index.html` oder fälschlich injizierte Umgebungsvariablen.
|
- Dies umgeht jegliches Caching von `index.html` oder fälschlich injizierte Umgebungsvariablen.
|
||||||
- UI-Marker auf `v2026-04-23.13 - RADICAL HTTPS PRIORITIZATION` aktualisiert.
|
- UI-Marker auf `v2026-04-23.13 - RADICAL HTTPS PRIORITIZATION` aktualisiert.
|
||||||
|
|
||||||
|
### 2026-04-23 10:45 - Version 14: CORS Reanimation
|
||||||
|
- **Problem**: Trotz HTTPS-Fix blockierte die CORS-Policy im Backend die Anfragen von `https://app.mo-code.at`.
|
||||||
|
- **Lösung**:
|
||||||
|
- `GlobalSecurityConfig.kt`: CORS explizit wieder aktiviert (`.cors { }`), da Microservices im Plan-B direkt (ohne Gateway) angesprochen werden könnten.
|
||||||
|
- `MailController.kt`: `@CrossOrigin` um explizite Header (`allowedHeaders = ["*"]`) und Methoden (`methods = [...]`) erweitert, um Preflight-Checks (OPTIONS) korrekt zu bedienen.
|
||||||
|
- UI-Marker auf `v2026-04-23.14 - CORS REANIMATION` aktualisiert.
|
||||||
|
|
||||||
|
### 2026-04-23 11:00 - Version 15: CORS Stability & Test Fix
|
||||||
|
- **Problem**: Aktivierung von `.cors { }` in `GlobalSecurityConfig.kt` verursachte `NoSuchBeanDefinitionException` in Spring-Integration-Tests, da keine `CorsConfigurationSource` Bean definiert war.
|
||||||
|
- **Lösung**:
|
||||||
|
- `GlobalSecurityConfig.kt`: Explizite `CorsConfigurationSource` Bean implementiert, die sowohl lokale Entwicklungsumgebungen (`localhost`) als auch produktive URLs (`*.mo-code.at`) whitelisted.
|
||||||
|
- Integration von `it.configurationSource(corsConfigurationSource())` in die `filterChain` zur Behebung der Testfehler.
|
||||||
|
- UI-Marker auf `v2026-04-23.15 - CORS STABILITY` aktualisiert.
|
||||||
|
- Verifiziert durch erfolgreichen Durchlauf des `EntriesIsolationIntegrationTest`.
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ fun MainAppContent() {
|
||||||
// Dezentraler Versions-Marker in der unteren rechten Ecke
|
// Dezentraler Versions-Marker in der unteren rechten Ecke
|
||||||
Box(modifier = Modifier.fillMaxSize().padding(8.dp), contentAlignment = Alignment.BottomEnd) {
|
Box(modifier = Modifier.fillMaxSize().padding(8.dp), contentAlignment = Alignment.BottomEnd) {
|
||||||
Text(
|
Text(
|
||||||
text = "v2026-04-23.13 - RADICAL HTTPS PRIORITIZATION",
|
text = "v2026-04-23.15 - CORS STABILITY",
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
color = Color.LightGray.copy(alpha = 0.5f)
|
color = Color.LightGray.copy(alpha = 0.5f)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user