在java REST请求期间偶尔出现"407 Proxy Authentication Required"错误



我正在尝试向我的一个客户端URL执行REST请求,以使用代理进行响应。在大多数时间我都可以使用我的代码来获得响应。但是有时我尝试使用我的代码发送请求,我收到的" 407代理身份验证需要"错误。这种情况很少发生,但是一旦我遇到此错误,对于每个连续的请求,我都会遇到相同的错误。但是当我使用Chrome的Postman Tool到Chrome到将生成相同的请求发送到同一URL,我将得到响应。但是,如果我再次尝试使用代码,我就会从邮递员那里得到响应,不仅开始从本地机器,而且从不同的机器中获得响应我也在运行代码的地方。我对这个问题感到非常困惑,无法弄清楚为什么会发生这种奇怪的情况。我在代码中缺少一些东西。

代码

public Map<String ,Object> ConnectRestService(MyRequest myRequest, String postURL, String httpProxy,int timeout int httpPort, Map<String ,Object> responseMap)
        throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CustomException{
    MyResponse myResponse = new MyResponse();
    Map<String ,Object> responseReturnMap = new HashMap<>();
    String output = "";
    TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType)
                throws java.security.cert.CertificateException {
            // TODO Auto-generated method stub
            return true;
        }
    };
    SSLContext sslContext = SSLContexts.custom()
            .loadTrustMaterial(null, acceptingTrustStrategy)
            .build();

    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
    HttpClient httpClient;
    httpClient = HttpClients.custom().setSSLSocketFactory(csf).setProxy(new HttpHost(httpProxy, httpPort)).build();
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.add("Content-type", "text/xml");
    httpHeaders.add("Accept", "text/xml");
    httpHeaders.add("access-control-allow-origin", "*");
    httpHeaders.add("content-encoding", "UTF-8");
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
    requestFactory.setConnectTimeout(timeout);

    try {
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        HttpEntity<MyRequest> entity = new org.springframework.http.HttpEntity<MyRequest>(
                myRequest, httpHeaders);
        ResponseEntity<String> response = restTemplate.exchange(postURL, HttpMethod.POST, entity, String.class);

    } catch (Exception ex) {
        logger.error(ex.getMessage(), ex);
    }
    return responseReturnMap;
}

请帮助我找出我在这里缺少的东西。

在发生407错误的情况下,您正在收到的响应必须包含一个特殊的Proxy-Authenticate标头。该标头将告诉您代理服务器期望的哪种身份验证。

您需要做的是在您的请求中包含Proxy-Authorization标头。代理授权标题的典型语法是Proxy-Authorization:<type-of-authentication-scheme> <credentials-for-authentication-at-proxy-server>

Proxy-Authenticate标头将使您知道您需要使用的身份验证方案的类型。

从我观察到的内容中,有些软件只是在这种情况下显示一个弹出式弹出式的弹出式。很多时候,此窗口"在"您正在工作的当前窗口的"后面",您甚至从未注意到凭证已被要求。因此,在许多情况下,作为人类的您甚至都没有在凭据中键入(不幸的是(弹出窗口在"当前工作窗口"后面显示。

因此,下次您面临这样一个问题时,快速检查是否有任何本地弹出窗口在幕后出现,并在您的凭据中迅速出现。

现在,我看到的另一件事是,再次连接到URL时,某些命令行工具(示例git等(将不得不浏览代理,这些工具有时会从事凭证管理的糟糕工作。为此,另一种方法是Windows中给出的"凭据管理器"。只需到达那里,然后在凭据管理器中"添加" URL,并在那里的凭据中"添加" URL,然后关闭所有命令行窗口并重试您的尝试。这次事情应该可以正常工作。

有凭证的"风味",一个带有"域名"的凭据(通常是您在公司代理后面(。

示例:您的Windows网络中的Windows登录ID可以是" Deepak",也可以是DomainName Deepak,因此请尝试在" Windows凭据管理器"中尝试它们作为用户名

尝试所有最好的。

https://support.microsoft.com/en-us/help/4026814/windows-accessing-credential-manager

您可以尝试指定源的来源,即从请求发出的位置,而不是使用星号。当浏览器或Firefox之类的浏览器可能并不总是正确地行为AFAIK,因为它看到遗失的原点可能是由于域而导致的,或者是由于CORS问题而引起的。

发送请求时,网络层试图查找资源,在这里似乎非简单的标题正在引起问题或混淆浏览器。 浏览器首先发送无数据选项请求[请求的基础第一个操作以查看要服务的内容,如果发现正确的话,请继续使用"真实请求",以确认服务器将接受合适的响应请求。

我认为内容类型不是以下任何一个,例如-Application/X-WWW-Form-urlenCoded,Multipart/form-data或text/plain/plain/plain,请求是非简单的。在此处提供有关非简单请求的更多信息。

另外,最好检查您的Java程序是否正在发送代理授权标题。检查TCP会话标题以查看是否丢失。

我可能要测试的另一部分是使用代理的REST模板。当然,您可能需要根据需要对其进行修改以与SSL合作,但以下是具有身份验证的基本示例。

 private final RestTemplate getProxiedRestTemplate() {
    RestTemplate r = null;
    if (isProxyActivated()) {
        HttpClientBuilder client = HttpClientBuilder.create();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        client.setProxy(new HttpHost("your ip", 8080 //or the port you want to use}
));
        if (withAuthentication()) {
            Credentials credentials = new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword());
            AuthScope authScope = new AuthScope("your ip", 8080);
            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(authScope, credentials);
            client.setDefaultCredentialsProvider(credsProvider);
        }
        requestFactory.setHttpClient(client.build());
        r = new RestTemplate(requestFactory);
    } else {
        r = new RestTemplate();
    }
    return r;
}

我希望该帖子有帮助或至少驱使您朝着更合适的方向开车。它来自代理服务器。在这种情况下,您必须在标题中添加 proxy-oterorization

尝试使用此代码段:

String data = "user:password"; // Here proxy user and password to be used.
String encodedValue = Base64.getEncoder().encodeToString(data.getBytes());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Proxy-Authorization", "Basic " + encodedValue); // You need to add proxy-authorization in the header.

读取此链接: Mozilla for oferxy-oterorization

请尝试清理您的代码。我认为每次创建RESTTEMPLATE时都会为垃圾收集器造成压力,但也可能导致其他问题。另外,您正在从方法中返回总是空的地图(可能在调试期间清洁代码...(。

要解决您的问题,请尝试检查您的TCP堆栈或TCP堆栈的代理服务器(如果有(出现时。例如,与这样的命令查看数量的打开连接:

ss -s

ps:重新启动客户端应用程序/服务器也有帮助吗?还有其他可能性如何"使其再次工作",而不是使用Postman?

最新更新