将哪些 Java 属性传递给 Java 应用程序以使用 http 代理进行身份验证

Posted

技术标签:

【中文标题】将哪些 Java 属性传递给 Java 应用程序以使用 http 代理进行身份验证【英文标题】:What Java properties to pass to a Java app to authenticate with a http proxy 【发布时间】:2015-06-03 20:45:34 【问题描述】:

我有一个 Java 应用程序正在尝试通过 http 代理访问 Web 服务。 Java 应用程序是我们无法访问其源代码的第 3 方应用程序。

它的启动可以通过传递 Java 启动参数等来配置。 我想知道可以传递哪些 java 属性,以便应用程序可以使用登录用户的 NTLM 凭据来验证代理连接?

当我通过 https.proxyHost 和 https.proxyPort(即 -Dhttps.proxyHost=abcd ... 到 jvm 命令行)时,我确实在日志中看到了差异。现在它失败并显示以下消息。

[WrapperSimpleAppMain] [AuthChallengeProcessor] ntlm authentication scheme selected 
INFO   | jvm 5    | 2015/06/03 14:49:25 | 2015-06-03 14:49:25,380 
INFO [WrapperSimpleAppMain] [HttpMethodDirector] No credentials available for NTLM <any realm>@proxy.ins.dell.com:80 
INFO  | jvm 5    | 2015/06/03 14:49:25 | Exiting due to fatal exception. 
INFO   | jvm 5    | 2015/06/03 14:49:25 | com.atlassian.bamboo.agent.bootstrap.RemoteAgentHttpException: HTTP status code 407 received in response to fingerprint request

我尝试传递 http.proxyUser 和 http.proxyPassword。那没有用。 我想知道什么是让 Java 应用透明地使用代理信息而无需更改代码的正确配置。

谢谢

【问题讨论】:

【参考方案1】:

最后我通过反复试验弄明白了。将 java.net.useSystemProxies=true 与 https.proxyPort 一起传递,https.proxyHost 解决了这个问题。

基本上java vm命令行搞定了

-Djava.net.useSystemProxies=true -Dhttps.proxyPort=80 -Dhttps.proxyHost=proxyserver.mycompany.com

我不必传递 https.proxyUser、https.proxyPassword。我相信代理身份验证使用的凭据与我的登录 NTLM 凭据相同。

【讨论】:

仅使用 -Djava.net.useSystemProxies=true 对我来说就足够了。从环境中读取的代理的主机和端口。 另外:密切关注 jdk 1.8.0_025 和 jdk 1.8.0_144 之间所做的更改!如果您的代理使用基本身份验证,似乎您必须将属性 jdk.http.auth.tunneling.disabledSchemes 设置为空字符串 - 或从中删除“基本”! jdk 默认在这里不使用基本身份验证!只需添加 -Djdk.http.auth.tunneling.disabledSchemes="" 之类的内容作为 jvm 选项以允许(所有)身份验证类型。【参考方案2】:

还需要为 NTLM 身份验证指定 NT 域。

-Dhttp.proxyUser=MyDomain/username

或通过设置

-Dhttp.auth.ntlm.domain=MyDomain

您还必须明确指示 HttpClient 将系统属性考虑在内,默认情况下它不会这样做

 CloseableHttpClient client = HttpClients.createSystem();

 CloseableHttpClient client = HttpClients.custom()
     .useSystemProperties()
     .build();

【讨论】:

我尝试了所有这些属性。它没有用。我无权访问该工具的源代码来强制它使用系统属性。 如果没有明确指示客户考虑这些属性(如上所示),则设置所有这些属性都无效。如果有问题的应用程序没有为您提供自定义 HttpClient 配置的方法,那么您就不走运了【参考方案3】:

Apache HttpClient 4.5.* 的工作示例

注意:除非您使用HttpClients.custom().useSystemProperties().build();,否则它不起作用

System.setProperty("http.proxyHost" , "myhost");
System.setProperty("http.proxyPort" , "myport");
System.setProperty("http.proxyUser" , "myuser");
System.setProperty("http.proxyPassword" , "mypassword");

CloseableHttpClient httpclient = HttpClients.custom().useSystemProperties().build();

try 

HttpGet httpGet = new HttpGet("http://www.google.com");

CloseableHttpResponse httpResponse = httpclient.execute(httpGet);

    try 
        System.out.println(httpResponse.getStatusLine());
        for (Header header : response.getAllHeaders()) 
            System.out.println("header " + header.getName() + " - " + header.getValue());
        

        String responseString = EntityUtils.toString(httpResponse.getEntity());
        System.out.println("responseString :" + responseString);

     finally 
        response.close();
    
 catch (Exception exception) 
    exception.printStackTrace();
 finally 
    httpclient.close();

您可以使用

设置属性,而不是使用 System.setProperty
-Dhttp.proxyHost="myhost" -Dhttp.proxyPort="myport" -Dhttp.proxyUser=myuser -Dhttp.proxyPassword="mypassword"

重要提示:如果您尝试访问 HTTPS 服务,您必须将属性更改为 https 如果您使用 https.* 属性并访问 http URL,它也不起作用

System.setProperty("https.proxyHost" , "myhost");
System.setProperty("https.proxyPort" , "myport");
System.setProperty("https.proxyUser" , "myuser");
System.setProperty("https.proxyPassword" , "mypassword");

CloseableHttpClient httpclient = HttpClients.custom().useSystemProperties().build();

try 
    HttpGet httpGet = new HttpGet("https://www.google.com");

API:https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/

纯 Java - 没有 Apache HttpClient

如果您使用 java.net.HttpURLConnection 类,您可以设置相同的 https.proxyHost 等属性

始终尊重对 https://... 连接使用 https.proxyHost 等,对 http://... 连接使用 http.proxyHost 等!

String uri = "https://www.google.com/";
HttpURLConnection connection = (HttpURLConnection) new URL(uri).openConnection();

InputStream response = connection.getInputStream();

BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

String inputLine; int x = 0;

while ((inputLine = in.readLine()) != null) 
    System.out.println(inputLine);
    x++; if (x > 4)  break;

in.close();
response.close();

【讨论】:

以上是关于将哪些 Java 属性传递给 Java 应用程序以使用 http 代理进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

java传递参数问题

我可以将哪些值传递给 f:ajax 标记的 event 属性?

将系统属性与 proguard 配置文件一起传递给 gradle proguardFile 属性

java 将Date转换为GregorianCalendar以传递给cxf客户端/服务器

通过 Gradle 运行 Java 类时传递系统属性和参数的问题

通过 Gradle 运行 Java 类时传递系统属性和参数的问题