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

使用Spring WebFlux WebClient从ADFS获取access_token失败

WebClient调用ADFS认证端点无响应问题排查与解决

我们的代码调用ADFS UI认证端点时,传入grant_type=authorization_code、redirect_uri=<redirect_uri>、client_id=<client_id>、code=<code>这4个参数,用JerseyClient能正常获取access_token,但换成Spring WebClient后完全拿不到响应,即便设置了followredirect(true)也无效,还遇到无法添加敏感请求头的问题,可按以下步骤排查解决:

1. 确保重定向配置正确传递请求头

WebClient默认的重定向策略会丢弃Cookie、Authorization这类敏感头,而ADFS的认证流程可能需要在重定向时保留这些头。可以通过Reactor Netty的HttpClient自定义重定向逻辑:

HttpClient httpClient = HttpClient.create()
        .followRedirect(true)
        // 重定向时复制原请求的所有头
        .redirect((req, res) -> Redirect.to(req.headers().copy()));

WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build();

2. 严格按照application/x-www-form-urlencoded格式提交参数

ADFS的token端点要求参数以表单形式提交,WebClient需要显式设置内容类型并正确构造表单参数,不能直接拼接在URL中:

// 构造表单参数
MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
formParams.add("grant_type", "authorization_code");
formParams.add("redirect_uri", "<你的redirect_uri>");
formParams.add("client_id", "<你的client_id>");
formParams.add("code", "<你的授权code>");

// 发送请求
Mono<Map> tokenResponse = webClient.post()
        .uri("https://你的ADFS域名/adfs/oauth2/token")
        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
        .body(BodyInserters.fromFormData(formParams))
        .retrieve()
        .bodyToMono(Map.class);

// 订阅获取结果(根据实际业务调整处理逻辑)
tokenResponse.subscribe(
        resp -> System.out.println("获取到的token:" + resp),
        err -> err.printStackTrace()
);

3. 自定义重定向策略处理复杂跳转

如果ADFS存在多次重定向或特殊的跳转逻辑,可以进一步自定义重定向策略,确保所有必要头都被携带:

HttpClient httpClient = HttpClient.create()
        .followRedirect(true)
        .redirect((request, response) -> {
            // 构造重定向请求,复制原请求的所有头信息
            HttpRequest redirectedReq = request.mutate()
                    .uri(response.responseHeaders().location())
                    .headers(headers -> headers.addAll(request.headers()))
                    .build();
            return Redirect.to(redirectedReq);
        });

4. 开启请求日志定位问题

添加日志过滤器,打印WebClient的请求、响应细节,排查是请求未发送、重定向失败还是ADFS返回了未被处理的错误:

WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        // 打印请求详情
        .filter(ExchangeFilterFunction.ofRequestProcessor(req -> {
            System.out.println("请求方法:" + req.method() + ",请求地址:" + req.url());
            req.headers().forEach((k, v) -> System.out.println(k + ": " + v));
            return Mono.just(req);
        }))
        // 打印响应详情
        .filter(ExchangeFilterFunction.ofResponseProcessor(resp -> {
            System.out.println("响应状态码:" + resp.statusCode());
            resp.headers().asHttpHeaders().forEach((k, v) -> System.out.println(k + ": " + v));
            return Mono.just(resp);
        }))
        .build();

5. 对比JerseyClient与WebClient的请求差异

用抓包工具(如Fiddler、Wireshark)分别捕获两种客户端的请求,对比请求头、参数编码、重定向流程的差异,找出WebClient缺失的配置(比如Jersey自动添加的特定头信息)。

内容的提问来源于stack exchange,提问作者user2113885

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:22:25