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

Spring WebFlux中如何修改响应的ReadOnlyHttpHeaders?遇UnsupportedOperationException

UnsupportedOperationException with ReadOnlyHttpHeaders in Spring Security Reactive

I've been stuck on this issue for an entire month with no resolution in sight. I can't find any relevant resources online, and I'm at my wit's end. I didn't configure any HTTP request headers manually, so I'm suspecting that Spring Security's default filters are setting them automatically?

  • org.springframework.web.reactive.function.server.DefaultServerResponseBuilder.AbstractServerResponse#writeTo
  • org.springframework.web.reactive.function.server.DefaultServerResponseBuilder.AbstractServerResponse#writeStatusAndHeaders
  • org.springframework.web.reactive.function.server.DefaultServerResponseBuilder.AbstractServerResponse#copy

Error Message

java.lang.UnsupportedOperationException: null
at org.springframework.http.ReadOnlyHttpHeaders.putAll(ReadOnlyHttpHeaders.java:138) ~[spring-web-6.0.11.jar:6.0.11]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: ...

Relevant Code Snippets

@Override
public Mono<Void> filter(@NonNull ServerWebExchange exchange, WebFilterChain chain) {
    return chain.filter(exchange)
        .contextWrite(context -> context.put(ServerHttpRequest.class, exchange.getRequest()));
}


@Bean
public SecurityWebFilterChain serverHttpSecurity(ServerHttpSecurity security,
                                             ReactiveAuthenticationManager authenticationManager,
                                             JwtConfigProperties jwtConfigProperties) {
    return security
        .headers(ServerHttpSecurity.HeaderSpec::disable)
        .csrf(ServerHttpSecurity.CsrfSpec::disable)
        .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
        .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
        .logout(ServerHttpSecurity.LogoutSpec::disable)
        .authenticationManager(authenticationManager)
        .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
        .addFilterAt(new JwtAuthenticationFilter(jwtConfigProperties), SecurityWebFiltersOrder.FIRST)
        .authorizeExchange(authorize -> authorize
            .anyExchange().permitAll()
        )
        .build();
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    return Mono.fromCallable(exchange::getRequest)
        .mapNotNull(sink -> sink.getHeaders().getFirst(HttpHeaders.AUTHORIZATION))
        .filter(sink -> sink.startsWith("Bearer "))
        .map(sink -> sink.substring("Bearer ".length()))
        .filter(StringUtils::hasText)
        .filter(sink -> JWTUtil.verify(sink, jwtConfigProperties.getSecret().getBytes()))
        .map(JWT::of)
        .map(sink -> {
            var username = sink.getPayload(RegisteredPayload.SUBJECT).toString();
            var principal = User.withUsername(username)
                .password("rob")
                .build();
            return new UsernamePasswordAuthenticationToken(principal, sink);
        })
        .flatMap(sink -> chain.filter(exchange)
            .contextWrite(ReactiveSecurityContextHolder.withAuthentication(sink))
        )
        .switchIfEmpty(chain.filter(exchange));
}


@PreAuthorize("isFullyAuthenticated()")
public Mono<String> test2() {
    return Mono.just("test2");
}

Content sourced from Stack Exchange, asked by Muscidae

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:40:06