Apache Сбой HttpClient с Java 11 в macOS - PullRequest
5 голосов
/ 13 апреля 2020

Я пытаюсь переместить мой код с Java 8 на Java 11, этот код ...

 private static String  readMultiHttpsUrlResultAsString(List<String> mbRecordingIds, String level) throws Exception
{
    String result = "";
    class NaiveTrustStrategy implements TrustStrategy
    {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
        {
            return true;
        }
    };

    SSLContext sslcontext = org.apache.http.ssl.SSLContexts.custom()
            .loadTrustMaterial(new NaiveTrustStrategy())
            .build();

    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext))
            .build();

    StringBuilder sb = new StringBuilder("?recording_ids=");
    for(String next:mbRecordingIds)
    {
        sb.append(next + ";");
    }
    sb.setLength(sb.length() - 1);
    try
    {
        String url = "https://acousticbrainz.org/api/v1"+level+sb;
        HttpGet httpget = new HttpGet(url);

        try (CloseableHttpResponse response = httpclient.execute(httpget);)
        {
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode!=HttpURLConnection.HTTP_OK)
            {
                return "";
            }
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity);
            EntityUtils.consume(entity);
        }
    }
    finally
    {
        httpclient.close();
    }
    return result;
}

}

здесь не удается с помощью (AdoptOpenJdk) Java 11.0.6 на MacOS,

SSLContext sslcontext = org.apache.http.ssl.SSLContexts.custom()
            .loadTrustMaterial(new NaiveTrustStrategy())
            .build();

Работает без проблем на Windows (также с использованием AdoptOpenJdk Java 11.0.6). Одно из отличий состоит в том, что в версии Windows используется jre-версия, созданная из jdk с jlink, тогда как в версии MacOS используется jop-версия AdoptOpenJDk. Сборка MacOS создается с использованием форка InfiniteKinds AppBundler

Это трассировка стека:

java.lang.NoClassDefFoundError: Could not initialize class sun.security.ssl.SSLContextImpl$TLSContext
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:315)
    at java.base/java.security.Provider$Service.getImplClass(Provider.java:1848)
    at java.base/java.security.Provider$Service.newInstance(Provider.java:1824)
    at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
    at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
    at java.base/javax.net.ssl.SSLContext.getInstance(SSLContext.java:168)
    at org.apache.http.ssl.SSLContextBuilder.build(SSLContextBuilder.java:269)
    at com.jthink.songkong.analyse.acousticbrainz.AcousticBrainz.readMultiHttpsUrlResultAsString(AcousticBrainz.java:409)
    at com.jthink.songkong.analyse.acousticbrainz.AcousticBrainz.readLowLevelData(AcousticBrainz.java:373)

Я использую Apache Httpclient 4.5.3 и использую эту библиотеку, потому что я я получаю данные из веб-службы, которая требует использования ssl.

Обновление Я добавил Пример теста в свой исходный код из приведенного ниже ответа и изменил мою сборку, чтобы сделать этот стартовый класс, когда приложение запускается, и оно дает мне эту трассировку стека (когда пакет запускается из командной строки с open с использованием java среды выполнения, встроенной в пакет приложением infinitekind appbundler)

Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.base/javax.crypto.Cipher.getInstance(Unknown Source)
    at java.base/sun.security.ssl.JsseJce.getCipher(Unknown Source)
    at java.base/sun.security.ssl.SSLCipher.isTransformationAvailable(Unknown Source)
    at java.base/sun.security.ssl.SSLCipher.<init>(Unknown Source)
    at java.base/sun.security.ssl.SSLCipher.<clinit>(Unknown Source)
    at java.base/sun.security.ssl.CipherSuite.<clinit>(Unknown Source)
    at java.base/sun.security.ssl.SSLContextImpl.getApplicableSupportedCipherSuites(Unknown Source)
    at java.base/sun.security.ssl.SSLContextImpl$AbstractTLSContext.<clinit>(Unknown Source)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Unknown Source)
    at java.base/java.security.Provider$Service.getImplClass(Unknown Source)
    at java.base/java.security.Provider$Service.newInstance(Unknown Source)
    at java.base/sun.security.jca.GetInstance.getInstance(Unknown Source)
    at java.base/sun.security.jca.GetInstance.getInstance(Unknown Source)
    at java.base/javax.net.ssl.SSLContext.getInstance(Unknown Source)
    at org.apache.http.ssl.SSLContextBuilder.build(SSLContextBuilder.java:389)
    at Example.main(Example.java:23)
Caused by: java.lang.SecurityException: Can not initialize cryptographic mechanism
    at java.base/javax.crypto.JceSecurity.<clinit>(Unknown Source)
    ... 17 more
Caused by: java.lang.SecurityException: Can't read cryptographic policy directory: unlimited
    at java.base/javax.crypto.JceSecurity.setupJurisdictionPolicies(Unknown Source)
    at java.base/javax.crypto.JceSecurity$1.run(Unknown Source)
    at java.base/javax.crypto.JceSecurity$1.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    ... 18 more

, что отличается от единицы У меня было раньше, но, может быть, это основная причина или это вводит в заблуждение?

Тогда как, если я просто запускаю java -jar songkong6.9.jar, он запускает Пример и печатает Загружен без ошибок, Если я укажу полный путь от / Library / Java также работает во всех случаях (Java 11 / Java 14 / JDk и JRE)

Обновление Основано на ответе ниже I добились определенного прогресса.

JRE, установленная на MacOS, содержит папку conf, когда JRE добавляется в мой комплект (SongKong) с помощью приложения InfiniteKinds, у него нет папки conf. У него есть папка lib / security, содержащая default.policy, но этого недостаточно.

pauls-Mac-mini:Home paul$ ls -lR lib/security
total 704
-rw-r--r--  1 paul  admin    1253 22 Apr 14:56 blacklisted.certs
-rw-r--r--  1 paul  admin  103147 22 Apr 14:56 cacerts
-rw-r--r--  1 paul  admin    8979 22 Apr 16:01 default.policy
-rw-r--r--  1 paul  admin  233897 22 Apr 14:56 public_suffix_list.dat

После установки встроенного пакета, если я вручную скопирую папку conf из установленной JRE в папку Home подключаемого модуля java

например,

/ Applications /SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home

местоположение, и код примера, и мой исходный код работают без ошибок при запуске из пакета. Похоже, что он ищет неограниченную папку и ее содержимое (два файла фактически одинаковы), поэтому, если я удаляю несколько файлов, и у меня остается

pauls-Mac-mini:Home paul$ pwd
/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home
pauls-Mac-mini:Home paul$ ls -lR conf
total 0
drwxr-xr-x  3 paul  admin  96 22 Apr 15:14 security

conf/security:
total 0
drwxr-xr-x  3 paul  admin  96 22 Apr 15:22 policy

conf/security/policy:
total 0
drwxr-xr-x  4 paul  admin  128 22 Apr 15:28 unlimited

conf/security/policy/unlimited:
total 16
-rw-r--r--  1 paul  admin  146 22 Apr 15:06 default_US_export.policy
-rw-r--r--  1 paul  admin  193 22 Apr 15:06 default_local.policy

, то она продолжает работать.

Проблема (не считая того, почему она не работает "из коробки"), я предполагаю, что не могу скопировать файлы в это местоположение для защищенного приложения времени выполнения, поэтому мне нужно хранить эти файлы политики в другом месте, чтобы их можно было установить как часть сборки appbundler. В качестве теста я переименовал conf folder conf.old folder и добавил следующий параметр в комплект

<string>-Djava.security.policy=/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home/conf.old/security/policy/unlimited/default_local.policy</string>

или вместо того, чтобы добавить файл политики

<string>-Djava.security.policy==/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home/conf.old/security/policy/unlimited/default_local.policy</string>

Но это не работает, я пробовал различные значения, но ничего не работает. Единственное, что работает, это оставляет его в подпапке conf, и тогда не имеет значения, передам ли я этот параметр или нет. (Я также попытался добавить -Dsecurity.manager в качестве другого варианта, но это просто вызвало новую ошибку о разрешениях при ведении журнала.)

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

В итоге с помощью Ani sh возникла проблема с отсутствующими файлами политик, а была только проблема с пакетом, созданным с AppBunder .

Код jdk действительно ожидал папку conf в JRE, она была в OpenJDk, но ни разу не была включена в мое приложение с AppBundler. Поэтому я скачал последний код AppBundler sr c и перестроил его, перестроил свой appbundle, и он был исправлен, теперь включена папка conf и приложение работает без ошибок.

2 голосов
/ 19 апреля 2020

Я протестировал код в Spring Tools Suite 4, AdoptedOpenJDK Java 11.0.6, macOS catalina 10.15.4 и Maven 3.8.1

Я взял часть кода, которая вызывала проблему.

Example.java:

package com.example;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.ssl.TrustStrategy;

class NaiveTrustStrategy implements TrustStrategy {

    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }

}

public class Example {

    public static void main(String... args) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
        SSLContext sslcontext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(new NaiveTrustStrategy())
                .build();
        System.out.println("Loaded");
    }

}

Примечание: я взял javax. net .ssl.SSLContext.

pom. xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <!-- <target>11</target> <source>11</source> -->
                    <verbose>true</verbose>
                    <fork>true</fork>
                    <executable>
                        /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/javac
                    </executable>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Выход (для тестирования): без ошибок

enter image description here

Я посмотрел по этой ссылке: https://github.com/TheInfiniteKind/appbundler/

Пожалуйста, измените JDK / JRE на 11.

Если проблема все еще существует, загрузите последнюю версию appbundler и попробуйте снова.


С Oracle Документация (https://www.oracle.com/java/technologies/javase-jce-all-downloads.html):

Текущие версии JDK не требуют этих файлов политики.

JDK 9 и более поздних версий поставляются и используют по умолчанию неограниченные файлы политики.

Неограниченные файлы политики требуются только для JDK 8, 7 и 6.

Вы можете загрузить эти файлы политики по ссылке на документацию выше.

Я думаю, что файлы политики могут отсутствовать или иметь какую-либо другую проблему. Пожалуйста, подтвердите.

...