在需要身份验证但不返回 407 的代理后面打开 http 连接

Posted

技术标签:

【中文标题】在需要身份验证但不返回 407 的代理后面打开 http 连接【英文标题】:openning http connection behind proxy which requires authentication but does not return 407 【发布时间】:2011-10-13 11:17:04 【问题描述】:

我们的小程序位于集成了代理身份验证的 Microsoft ISA Server 后面。Isa 代理服务器为没有身份验证凭据的连接返回 http 405(NOT 407)。我的 java.net.Authenticator 类不会被调用。 在这种情况下,我如何验证与代理服务器的连接? Applet 使用 java1.6 签名和编译。 URLConnection 类用于连接。

【问题讨论】:

您可以直接访问 HttpURLConnection 还是通过其他库? @laz: 是的,我可以访问它。 【参考方案1】:

我可以看到解决此问题的两种方法,但都不是很理想。首先,我猜您已经验证发送带有授权信息的请求不会产生405 响应代码?如果答案是肯定的,您可以尝试将请求中的Proxy-authorization标头设置为标头:

URL url = new URL("http://location");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Proxy-authorization", authorizationValue);

该标头的格式将取决于代理服务器所需的授权方案,因此您必须针对您的特定场景进行一些研究。

第二种方法涉及子类化一个内部 JDK 类来欺骗响应代码以强制使用正常的代理身份验证路径。首先,这是子类:

public class HttpURLConnection extends sun.net.www.protocol.http.HttpURLConnection 

    @Override
    public int getResponseCode() throws IOException 
        int code = super.getResponseCode();
        if (code == HTTP_BAD_METHOD) 
            code = HTTP_PROXY_AUTH;
            responseCode = code;
        
        return code;
    


当然,这将掩盖任何实际的405 响应,因此可能会产生意想不到的后果。告诉 URL 对象使用它需要 java.net.URLStreamHandlerFactory 的子类:

public class URLStreamHandlerFactory extends java.net.URLStreamHandlerFactory 
    @Override
    URLStreamHandler createURLStreamHandler(String protocol) 
        if (!protocol.equals("http")) 
            return null;
         else 
            return new java.net.URLStreamHandler 
                protected String proxy;
                protected int proxyPort;

                public Handler () 
                    proxy = null;
                    proxyPort = -1;
                

                public Handler (String proxy, int port) 
                    this.proxy = proxy;
                    this.proxyPort = port;
                

                @Override
                protected java.net.URLConnection openConnection(URL u) throws IOException 
                        return openConnection(u, (Proxy)null);
                

                @Override
                protected java.net.URLConnection openConnection(URL u, Proxy p) throws IOException 
                        return new HttpURLConnection(u, p, this);
                

                @Override
                protected int getDefaultPort() 
                    return 80;
                

            
        
    

然后您可以通过在初始化代码中的某处调用URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory()); 来使用此对象。我发现this site 和this site 对于查看核心Java 类的工作方式很有用。如果您需要支持 HTTPS,则需要对该协议进行类似的更改。

希望这些解决方案之一对您有用。我不完全确定后一种方法是否可以在 Applet 的安全约束内工作。前者应该。如果您能够使用它,使用不同的 HTTP 库(例如 Apache HttpComponents)也可能更容易做到这一点。

【讨论】:

在方法一中,标头将是代理授权?或代理身份验证标头?.身份验证协议有时会有所不同(ntlm或kerberos),因此我认为这种方法会非常困难?在方法二中:您认为设置响应代码就足够了吗?我认为还需要设置一些关于需要哪种身份验证的标题? 方法是Proxy-authorization。如果计划发生变化,这听起来将非常困难。所以它返回405 但不需要什么类型的身份验证?在这种情况下,是的,您还必须包含任何必要的 Proxy-Authenticate 响应标头。是代理服务器配置错误还是什么?这听起来像是严重破坏的行为!服务器是否可以正常工作,例如浏览器? 我不知道他们为什么这样配置它,但他们就是这么做的。该网络上的客户端对他们主要在本地浏览的网络的访问非常有限。显然他们现在无法更改它,因为可能会出现问题,因此他们希望在客户端解决这个问题。 我想我会尝试我当时建议的第一种方法并尝试创建适当的标头值。

以上是关于在需要身份验证但不返回 407 的代理后面打开 http 连接的主要内容,如果未能解决你的问题,请参考以下文章

远程服务器返回错误:(407) 需要代理身份验证

远程服务器返回错误:(407) 需要代理身份验证

需要 TFS PowerTools 代理身份验证 HTTP 代码 407

HTTPS URL 的基本代理身份验证返回 HTTP/1.0 407 需要代理身份验证

SSIS 脚本转换错误远程服务器返回错误:(407) 需要代理身份验证

VS 2013远程服务器返回错误:(407)需要代理身份验证