无法通过代理隧道。代理通过https返回“HTTP/1.1 407”。

31

我遇到了Java6/8的一个奇怪行为。我尝试通过标准的Java Authenticator穿越需要基本用户身份验证的代理。但如果我首先访问https URL,则会抛出异常:

java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"

但是,如果我先访问http URL,然后再访问https URL,https访问就可以正常工作。

给定代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URL;

public class ProxyPass {
    public ProxyPass( String proxyHost, int proxyPort, final String userid, final String password, String url ) {

    try {
            /* Create a HttpURLConnection Object and set the properties */
            URL u = new URL( url );
            Proxy proxy = new Proxy( Proxy.Type.HTTP, new InetSocketAddress( proxyHost, proxyPort ) );
            HttpURLConnection uc = (HttpURLConnection) u.openConnection( proxy );

            Authenticator.setDefault( new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    if (getRequestorType().equals( RequestorType.PROXY )) {
                        return new PasswordAuthentication( userid, password.toCharArray() );
                    }
                    return super.getPasswordAuthentication();
                }
            } );
            uc.connect();
            /* Print the content of the url to the console. */
            showContent( uc );
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void showContent( HttpURLConnection uc ) throws IOException {
        InputStream i = uc.getInputStream();
        char c;
        InputStreamReader isr = new InputStreamReader( i );
        BufferedReader br = new BufferedReader( isr );
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println( line );
        }
    }

    public static void main( String[] args ) {
        String proxyhost = "proxyHost";
        int proxyport = proxyPort;
        final String proxylogin = proxyUser;
        final String proxypass = proxyPass;

        String url = "http://www.google.de";
        String surl = "https://www.google.de";

//            new ProxyPass( proxyhost, proxyport, proxylogin, proxypass, url );  // uncomment this line to see that the https request works!
//            System.out.println( url + " ...ok" );   // uncomment this line to see that the https request works!
        new ProxyPass( proxyhost, proxyport, proxylogin, proxypass, surl );
        System.out.println( surl + " ...ok" );
    }

有什么建议或想法吗?

3个回答

48

Java 8 Update 111的更改:

现在,在为HTTPS设置隧道时需要基本身份验证的代理默认将不再成功。如果需要,可以通过从jdk.http.auth.tunneling.disabledSchemes网络属性中删除Basic,或者在命令行上设置一个系统属性与该名称相同且值为空("")来重新激活此身份验证方案。

http://www.oracle.com/technetwork/java/javase/8u111-relnotes-3124969.html

您有以下选择:

  • 升级代理的身份验证方案(例如Digest访问身份验证),以解决此问题(出于安全考虑)。
  • 或者通过使用以下参数运行Java来解决问题:
java -Djdk.http.auth.tunneling.disabledSchemes=""

1
有了这个选项设置,现在可以像建议的那样工作了。非常感谢这个提示! - PPr

37

您需要编辑变量jdk.http.auth.tunneling.disabledSchemesjdk.http.auth.proxying.disabledSchemes,将它们设为空白,如下所示:

jdk.http.auth.tunneling.disabledSchemes=
jdk.http.auth.proxying.disabledSchemes=

在我的情况中,我在这个文件中找到了:

jdk1.8.0_111/jre/lib/net.properties


这很有帮助,谢谢。 - mvw
@Marcus 不需要更新JDK属性,你可以使用java -Djdk.http.auth.tunneling.disabledSchemes=""命令。 - user1697575
1
@user1697575 这正是我在答案中建议的。 - Marcus
4
在Java 11上,它在jdk-11/conf/net.properties中。 - Thunderforge
1
Jdk 1.8.0 的最佳答案。其他解决方案均无效。 - Omkar Kulkarni

4
这可能会有帮助:
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "false");
System.setProperty("jdk.http.auth.proxying.disabledSchemes", "false");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接