2016-11-16 8 views
0

Это немного странно, и я сделал достаточно исследований, чтобы найти причину и решение этой проблемы. Моя цель - загрузить zip-файл с защищенного URL-адреса, который также требует входа в систему. Все работает отлично, когда я использую зависимость apache HTTPClient maven от версии 4.3.6. Тем не менее, я не могу использовать эту версию из-за того, что моя зависимость maven от aws-sdk-java-ядра также имеет зависимость httpclient и использование v4.3.6 заставляет aws-sdk-java жаловаться на исключение среды выполнения NoSuchMethod. Я понимаю эту проблему. Причина в том, что зависимость apache httpclient v4.3.6 более близка к дереву зависимостей maven, чем версия (4.5.1), используемая зависимостью aws-sdk-java-core. Во всяком случае, я сокращу более подробную информацию об этом, потому что я уверен, что я должен сделать все, чтобы работать с одной версией зависимости maven, а не использовать несколько версий одной и той же банки. Назад к оригинальному вопросу. Поскольку я не могу использовать v4.3.6, я сказал, что мой код использует v4.5.1, и это когда код загрузки файла начал давать проблемы. Когда я использую httpclient v4.5.1, ответ дает мне следующий html-контент, а не дает мне zip-файл, который у меня есть на запрошенном https-адресе.Загрузка zip-файла работает с apache httpclient v4.3.6, но сбой для другой версии

<html> 
<HEAD><META HTTP-EQUIV='PRAGMA' CONTENT='NO-CACHE'><META HTTP-EQUIV='CACHE-  
CONTROL' CONTENT='NO-CACHE'> 
<TITLE>SAML 2.0 Auto-POST form</TITLE> 
</HEAD> 
<body onLoad="document.forms[0].submit()"> 
<NOSCRIPT>Your browser does not support JavaScript. Please click the  
'Continue' button below to proceed. <br><br> 
</NOSCRIPT> 
<form action="https://githubext.deere.com/saml/consume" method="POST"> 
<input type="hidden" name="SAMLResponse" value="PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERl"> 
<input type="hidden" name="RelayState" value="2F1HpzrUy5FdX"> 
<NOSCRIPT><INPUT TYPE="SUBMIT" VALUE="Continue"></NOSCRIPT> 
</form> 
</body> 
</html> 

Когда я использую v4.3.6, ответ дает мне почтовый файл как ожидаемый ответ. Я попытался вручную отправить этот html-контент, добавив больше кода, но ответ остается неповрежденным. Исходный код, который у меня есть для загрузки файла, приведен ниже.

@Component 
public class FileDAO { 

    public static void main(String args[]) throws Exception{ 
     new FileDAO().loadFile("https://some_url.domain.com/zipball/master","myfile.zip"); 
    } 


    public String loadFile(String url, String fileName) throws ClientProtocolException, IOException { 

     HttpClient client = login(); 
     HttpResponse response = client.execute(new HttpGet(url)); 
     int statusCode = response.getStatusLine().getStatusCode(); 
     if (statusCode == 200) { 
      String unzipToFolderName = fileName.replace(".", "_"); 
      FileOutputStream outputStream = new FileOutputStream(new File(fileName)); 
      writeToFile(outputStream, response.getEntity().getContent());    
      return unzipToFolderName; 
     } else { 
      throw new RuntimeException("error downloading file, HTTP Status code: " + statusCode); 
     } 
    } 

    private void writeToFile(FileOutputStream outputStream, InputStream inputStream) { 
     try { 
      int read = 0; 
      byte[] bytes = new byte[1024]; 
      while ((read = inputStream.read(bytes)) != -1) { 
       outputStream.write(bytes, 0, read); 
      } 
     } catch (Exception ex) { 
      throw new RuntimeException("error writing zip file, error message : " + ex.getMessage(), ex); 
     } finally { 
      try { 
       outputStream.close(); 
       inputStream.close(); 
      } catch (Exception ex) {} 
     } 
    } 

    private HttpClient login() throws IOException { 
     HttpClient client = getHttpClient(); 

     HttpResponse response = client.execute(new HttpGet("https://some_url.domain.com")); 
     String responseBody = EntityUtils.toString(response.getEntity()); 
     Document doc = Jsoup.parse(responseBody); 
     org.jsoup.select.Elements inputs = doc.getElementsByTag("input"); 
     int statusCode = response.getStatusLine().getStatusCode(); 
     if (statusCode == 200) { 
      HttpPost httpPost = new HttpPost("https://some_url.domain.com/saml/consume"); 
      List<NameValuePair> data = new ArrayList<NameValuePair>(); 
      data.add(new BasicNameValuePair("SAMLResponse", doc.select("input[name=SAMLResponse]").val())); 
      data.add(new BasicNameValuePair("RelayState", doc.select("input[name=RelayState]").val())); 
      httpPost.setEntity(new UrlEncodedFormEntity(data)); 
      HttpResponse logingResponse = client.execute(httpPost); 
      int loginStatusCode = logingResponse.getStatusLine().getStatusCode(); 
      if (loginStatusCode != 302) { 
       throw new RuntimeException("clone repo dao. error during login, HTTP Status code: " + loginStatusCode); 
      } 
     } 
     return client; 
    } 

    private HttpClient getHttpClient() { 
     CredentialsProvider provider = new BasicCredentialsProvider(); 
     UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("userId", "password"); 
     provider.setCredentials(AuthScope.ANY, credentials); 
     return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build(); 
    } 
} 

Я все еще анализирую, что происходит с версиями apache httpclient, отличными от 4.3.6. Тот же код работает с 4.3.6, но не с версией выше 4.3.6. Любая помощь действительно оценена. Спасибо вам всем.

ответ

1

Проблема решена. Пройдя через документацию apache httpclient с серьезной отладкой журналов, я мог бы решить эту проблему. Мне пришлось создать два журнала сервера, один для v4.3.6 и другой для v4.5.2. Я начал сравнивать журналы сервера и обнаружил, что виновником был тип файла cookie. Тип файла cookie в старой версии был (автоматически) настроен как BEST_MATCH, и он работал. Однако для v4.5.2 тип cookie BEST_MATCH устарел из apache. Я пытался с настройками cookie после добавления некоторого кода, но cookie, отправленный ответом сервера, не соответствовал типу cookie DEFAULT, который я сконфигурировал в клиентском коде. Это привело к тому, что cookie не был правильно настроен, и поэтому ответ возвращал ответ SAML (страница входа снова) вместо zip-файла.

Apache cookie spec говорит, что это для спецификации печенья:

По умолчанию: По умолчанию политики печенья является синтетической политикой, которая улавливает либо RFC 2965, RFC 2109 или проект Netscape реализации совместимом на основе свойств куков, отправленных с HTTP-ответ (например, атрибут версии, теперь устаревший). Эта политика будет устаревать в пользу стандартной (совместимой с RFC 6265) реализации в следующем выпуске HttpClient. Стандартные строгие: политики Государственного управления соответствует синтаксису и семантика хорошо себя профиль, определенному в RFC 6265, раздел 4.

Я обновил конфигурацию куков STANDARD_STRICT режим и все начали работать с последней версией 4.5.2.

Вот обновленный метод getHttpClient():

private CloseableHttpClient getHttpClient() { 
    CredentialsProvider provider = new BasicCredentialsProvider(); 
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(gitUserId, gitPassword); 
    provider.setCredentials(AuthScope.ANY, credentials); 
    RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build(); 
    return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setDefaultRequestConfig(config).setRedirectStrategy(new LaxRedirectStrategy()).build(); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^