对于 Jena 中基于 JDK 的 HTTP 栈(自 Jena 4.3 引入),要配置传给查询构建器的 transport。SPARQL 端点的密码和代理的密码可能由不同的机器索取。

import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.http.HttpClient;
import org.apache.jena.sparql.exec.http.QueryExecutionHTTP;

var http = HttpClient.newBuilder()
    .proxy(ProxySelector.of(
        new InetSocketAddress("proxy.example", 8080)))
    .authenticator(proxyAuthenticator)
    .build();

var execution = QueryExecutionHTTP.service(endpointUrl)
    .httpClient(http)
    .query("ASK { ?s ?p ?o }")
    .build();

这个片段构建一次查询执行。endpointUrl 是实际的 SPARQL 服务 URL;proxyAuthenticator 是应用程序提供的 java.net.Authenticator。请按照应用程序正常的查询生命周期来执行并关闭这次查询执行。

在该认证器的 getPasswordAuthentication 方法中,只有当 getRequestorType() == RequestorType.PROXY 且请求的主机和端口与已配置的中介一致时,才返回代理的 PasswordAuthentication。对无关的质询返回 null。把这个对象附加到客户端上,可以让这一选择只对该客户端生效。

读懂代理在要求什么

407 响应表示出现了代理认证质询。它的 Proxy-Authenticate 头会说明所提供的方案;仅凭状态码无法区分 Basic 与 NTLM 或其他方案。

要把这份方案清单与已部署的 JDK 客户端的能力和认证策略对照。提供用户名和密码并不会凭空增加不受支持的方案。对于 HTTPS 目标,还要检查 JDK 的 jdk.http.auth.tunneling.disabledSchemes 策略;普通 HTTP 代理有单独的 disabledSchemes 设置。JDK 对 CONNECT 的 Basic 认证默认值就是这类策略检查之一。

使用 Apache HttpClient 和 SimpleNTAuthenticator 的历史 Jena 示例属于更早一代的 transport。如果企业代理要求当前 transport 不支持的认证机制,应与网络管理员商定受支持的集成方式,而不是硬把那些旧的认证对象塞进新的构建器。

相关文章