Spring WebClient如何获取服务端响应的Session Cookie用于后续请求
WebClient 会话保持实现方案
Spring WebClient 默认不会自动持久化响应返回的 Cookie,你可以根据需求选择以下两种方案实现认证后的会话保持:
方案1:开启自动Cookie管理(推荐)
直接给 WebClient 绑定支持Cookie存储的Reactor Netty客户端,同域名下的Cookie会自动存储、自动携带,完全不需要手动解析和写入请求头,代码可维护性最高。
import io.netty.handler.codec.http.cookie.ClientCookieDecoder; import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; import reactor.netty.http.client.cookie.InMemoryCookieStore; import java.time.Duration; import java.util.HashMap; import java.util.Map; // 初始化全局复用的WebClient实例,不要每次请求都新建 HttpClient httpClient = HttpClient.create() .responseTimeout(Duration.ofSeconds(10)) // 配置Cookie编解码和内存存储 .cookieCodec(ServerCookieEncoder.STRICT, ClientCookieDecoder.STRICT) .cookieStore(new InMemoryCookieStore()); WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); // 认证请求:正常携带x-api-key发起请求即可,认证成功返回的Session Cookie会自动存入内存 String authResp = webClient.get() .uri("http://localhost:8081/authenticate") .header("x-api-key", "123456789") .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(String.class) .block(); Map<String, Object> query = new HashMap<>(); query.put("collection", "student"); // 查询请求:无需手动加Cookie头,客户端会自动把之前存储的Session Cookie带过去 String queryResp = webClient.post() .uri("http://localhost:8081/query") .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(query)) .retrieve() .bodyToMono(String.class) .block();
方案2:手动提取并写入Cookie
如果你需要自定义Cookie处理逻辑(比如持久化Cookie到外部存储、打印调试Cookie内容),可以手动从认证响应的Set-Cookie头中提取会话标识,再写入后续请求的Cookie头中。
import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import java.util.HashMap; import java.util.List; import java.util.Map; WebClient webClient = WebClient.builder().build(); // 用数组存Cookie值,适配lambda的变量只读要求 final String[] sessionCookie = {null}; String authResp = webClient.get() .uri("http://localhost:8081/authenticate") .header("x-api-key", "123456789") .accept(MediaType.APPLICATION_JSON) // 从响应中提取Set-Cookie头 .exchangeToMono(response -> { List<String> cookieHeaders = response.headers().get(HttpHeaders.SET_COOKIE); if (cookieHeaders != null && !cookieHeaders.isEmpty()) { // 截取Cookie键值对,去掉Path、HttpOnly、过期时间等属性 // 如果有多个有效Cookie,遍历后用分号拼接即可 sessionCookie[0] = cookieHeaders.get(0).split(";")[0]; } return response.bodyToMono(String.class); }) .block(); Map<String, Object> query = new HashMap<>(); query.put("collection", "student"); String queryResp = webClient.post() .uri("http://localhost:8081/query") .contentType(MediaType.APPLICATION_JSON) // 手动写入Cookie头 .header(HttpHeaders.COOKIE, sessionCookie[0]) .body(BodyInserters.fromValue(query)) .retrieve() .bodyToMono(String.class) .block();
注意事项
- 优先选择自动Cookie管理方案,手动处理时需要自行适配Cookie的作用域、过期时间、Path匹配规则,容易遗漏逻辑导致会话失效
- WebClient实例建议全局单例复用,频繁新建实例会导致Cookie存储随实例销毁,无法实现会话保持
内容的提问来源于stack exchange,提问作者Aws AbuObeid
相关产品推荐
相关产品推荐

