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

如何在Java 11 HTTP Client的URL中包含问号(?)?

问题分析

第三方提供的URL中,?被要求作为路径的一部分存在(而非标准URL中用于分隔路径和查询参数的符号),直接使用URLEncoder对包含?的整个片段编码后,ASP后端仍触发危险路径检测,报错如下:

A potentially dangerous Request.Path value was detected from the client (?).
at System.Web.HttpRequest.ValidateInputIfRequiredByConfig()
at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)

当前代码存在两个核心问题:一是构建URI时缺失https://协议头,导致URI解析异常;二是整体编码方式无法精准适配第三方URL的特殊结构要求。

解决方案

1. 修复URI协议缺失问题

必须补全https://协议头,确保URI被正确解析,避免主机名与路径混淆。

2. 精准编码URL各部分

拆分URL的静态路径、特殊字符片段和?后的内容,分别编码后拼接,确保?被转义为路径合法的%3F,同时保留第三方要求的结构。

修改后的完整代码:

import java.net.*;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public String getAdventPerformanceData(@RequestBody AdventDataRequest requestMessage) throws IOException, InterruptedException {
    HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .proxy(ProxySelector.of(new InetSocketAddress(adventAuthenticator.getProxyURL(),
                    adventAuthenticator.getProxyPort())))
            .build();

    // 拆分URL各组成部分
    String basePath = "/Performance";
    String pathFragment = "(Portfolios=['AccountNo'],FromDate=2022-09-20,ToDate=2022-09-20,ClassificationID=-8)";
    String expandContent = "$expand=Portfolio($select=PortfolioCode,ReconciliationStatus),security($select=*)";

    // 分别编码特殊片段和扩展内容,手动指定?的转义值%3F
    String encodedFragment = URLEncoder.encode(pathFragment, StandardCharsets.UTF_8);
    String encodedExpand = URLEncoder.encode(expandContent, StandardCharsets.UTF_8);
    String fullEncodedPath = basePath + encodedFragment + "%3F" + encodedExpand;

    // 构建完整合法的URI
    URI uri = URI.create("https://mybadurl.com" + fullEncodedPath);

    HttpRequest request = HttpRequest.newBuilder()
            .GET()
            .uri(uri)
            .header("authorization", "BEARER " + adventAuthenticator.getToken())
            .build();

    HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

    return response.body();
}

3. 备选方案:使用URI构造器自动转义

如果手动编码仍有问题,可直接使用Java原生URI构造器,它会自动处理路径中的非法字符转义:

// 构造器自动转义路径中的特殊字符,无需手动编码
URI uri = new URI(
        "https",
        "mybadurl.com",
        "/Performance(Portfolios=['AccountNo'],FromDate=2022-09-20,ToDate=2022-09-20,ClassificationID=-8)?$expand=Portfolio($select=PortfolioCode,ReconciliationStatus),security($select=*)",
        null,
        null
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:35:18