phpQuery и QueryPath чрезвычайно похожи в репликации свободного API jQuery. Вот почему они - два из самых простых подходов к правильно анализируют HTML в PHP.
Примеры для QueryPath
В основном вы сначала создаете запрашиваемое дерево DOM из строки HTML:
$qp = qp("title
..."); // or give filename or URL
Результирующий объект содержит полное древовидное представление документа HTML. Он может быть пройден с использованием методов DOM. Но общий подход заключается в использовании селекторов CSS, например, в jQuery:
$qp->find("div.classname")->children()->...;
foreach ($qp->find("p img") as $img) {
print qp($img)->attr("src");
}
. В основном вы хотите использовать простые #id
и .class
или DIV
селектор тэгов для ->find()
. Но вы также можете использовать операторы XPath , которые иногда бывают быстрее. Также типичные методы jQuery, такие как ->children()
и ->text()
и особенно ->attr()
, упрощают извлечение правильных фрагментов HTML. (И уже имеют свои SGML-объекты, декодированные.)
$qp->xpath("//div/p[1]"); // get first paragraph in a div
QueryPath также позволяет вводить новые теги в поток (->append
), а затем выводить и префикс обновленного документа (->writeHTML
). Он может не только анализировать искаженный HTML, но также различные диалекты XML (с пространствами имен) и даже извлекать данные из микроформатов HTML (XFN, vCard).
$qp->find("a[target=_blank]")->toggleClass("usability-blunder");
.
phpQuery или QueryPath?
Обычно QueryPath лучше подходит для манипулирования документами. В то время как phpQuery также реализует некоторые псевдо-AJAX-методы (только HTTP-запросы), более похожие на jQuery. Говорят, что phpQuery часто быстрее, чем QueryPath (из-за меньшего количества общих функций).
Для получения дополнительной информации о различиях см. это сравнение на машине обратного пути от tagbyte.org . (Оригинальный источник пропал без вести, так что вот ссылка интернет-архива. Да, вы все равно можете найти недостающие страницы, люди.)
И вот всеобъемлющее введение QueryPath .
Преимущества
->find("a img, a object, div a")
В моем случае я запускаю MacOs High Sierra с Java 1.6. Файл cacert находится в другом месте, чем указано выше в ответе Gabe Martin-Dempesy. Файл cacert также был связан с другим местоположением (/ Library / Internet Plug-Ins / JavaAppletPlugin.plugin / Contents / Home / lib / security / cacerts).
Используя FireFox, я экспортировал сертификат с рассматриваемого веб-сайта в локальный файл под названием «exportedCertFile.crt». Оттуда я использовал keytool для переноса сертификата в файл cacert. Это устранило проблему.
bash-3.2# cd /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/
bash-3.2# keytool -importcert -file ~/exportedCertFile.crt -alias example -keystore cacerts -storepass changeit
Ответ @Gabe Martin-Dempesy мне помогает. И я написал небольшой сценарий, связанный с ним.
Установить сертификат с хоста:
> sudo ./java-cert-importer.sh example.com
Удалить уже установленный сертификат.
> sudo ./java-cert-importer.sh example.com --delete
java-cert- importer.sh
#!/usr/bin/env bash
# Exit on error
set -e
# Ensure script is running as root
if [ "$EUID" -ne 0 ]
then echo "WARN: Please run as root (sudo)"
exit 1
fi
# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }
# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}
# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)
usage: ./java-cert-importer.sh <host> [ <port> | default=443 ] [ -d | --delete ]
EOF
exit 1
fi;
if [ "$JAVA_HOME" ]; then
javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
javahome="$(/usr/libexec/java_home)/jre"
fi
if [ ! "$javahome" ]; then
echo "WARN: Java home cannot be found."
exit 1
elif [ ! -d "$javahome" ]; then
echo "WARN: Detected Java home does not exists: $javahome"
exit 1
fi
echo "Detected Java Home: $javahome"
# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"
if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
echo "Certificate is deleted for ${host}"
exit 0
fi
# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port
# create temp file
tmpfile="/tmp/${host}.$$.crt"
# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}
echo "Java CaCerts Backup: ${cacertsbackup}"
# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}
# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit
# Remove temp certificate file
rm ${tmpfile}
# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")
# Show results to user
if [ "$result" ]; then
echo "Success: Certificate is imported to java cacerts for ${host}";
else
echo "Error: Something went wrong";
fi;
./java-cert-importer.sh example.com 1234
). Вот и все.
– lepe
24 April 2017 в 07:30
Это также может быть вызвано использованием сертификатов GoDaddy с Java 7, подписанных с использованием SHA2.
Chrome и все другие браузеры начинают обесценивать сертификаты SSL, подписанные с использованием SHA1, поскольку это не так безопасно ,
Более подробную информацию о проблеме можно найти здесь , а также о том, как ее решить на вашем сервере, если вам нужно сейчас.
Проблема возникает, когда у вашего сервера есть подписанный сертификат. Чтобы обойти это, вы можете добавить этот сертификат в список доверенных сертификатов вашей JVM.
В этой статье автор описывает, как получить сертификат из вашего браузера и добавить его в файл cacerts вашей JVM. Вы можете отредактировать файл JAVA_HOME/jre/lib/security/cacerts
или запустить приложение с параметром -Djavax.net.ssl.trustStore
. Проверьте, какой JDK / JRE вы используете, так как это часто является источником путаницы.
См. Также: Как разрешены имена серверов сертификатов SSL / Можно ли добавлять альтернативные имена с помощью keytool? Если вы столкнулись с java.security.cert.CertificateException: No name matching localhost found
исключением.
Вот что надежно работает для меня на macOS. Обязательно замените example.com и 443 фактическим именем хоста и портом, к которому вы пытаетесь подключиться, и укажите пользовательский псевдоним. Первая команда загружает предоставленный сертификат с удаленного сервера и сохраняет его локально в формате x509. Вторая команда загружает сохраненный сертификат в хранилище доверия SSL Java.
openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit
Для тех, кто любит Debian и предварительно упакованную Java:
sudo mkdir /usr/share/ca-certificates/test/ # don't mess with other certs
sudo cp ~/tmp/test.loc.crt /usr/share/ca-certificates/test/
sudo dpkg-reconfigure --force ca-certificates # check your cert in curses GUI!
sudo update-ca-certificates --fresh --verbose
Не забудьте проверить /etc/default/cacerts
для:
# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes
Чтобы удалить cert:
sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose
Версия AVG 18.1.3044 (с Windows 10) вмешивается в мое локальное приложение Spring.
Решение: войдите в раздел AVG под названием «Интернет и электронная почта» и отключите «защиту электронной почты». AVG блокирует сертификат, если сайт не защищен.
Мне удалось заставить его работать только с кодом, т. е. не нужно использовать keytool:
import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class Test
{
private static final DynamicIntProperty MAX_TOTAL_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
private static final DynamicIntProperty ROUTE_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
private static final DynamicIntProperty CONNECT_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connect.timeout", 60000);
private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.socket.timeout", -1);
private static final DynamicIntProperty CONNECTION_REQUEST_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connectionrequest.timeout", 60000);
private static final DynamicBooleanProperty STALE_CONNECTION_CHECK = DynamicPropertyFactory.getInstance().getBooleanProperty("X.checkconnection", true);
public static void main(String[] args) throws Exception
{
SSLContext sslcontext = SSLContexts.custom()
.useTLS()
.loadTrustMaterial(null, new TrustStrategy()
{
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
return true;
}
})
.build();
SSLIOSessionStrategy sslSessionStrategy = new SSLIOSessionStrategy(sslcontext, new AllowAll());
Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()
.register("http", NoopIOSessionStrategy.INSTANCE)
.register("https", sslSessionStrategy)
.build();
DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT);
PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, sessionStrategyRegistry);
connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS.get());
connectionManager.setDefaultMaxPerRoute(ROUTE_CONNECTIONS.get());
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(SOCKET_TIMEOUT.get())
.setConnectTimeout(CONNECT_TIMEOUT.get())
.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT.get())
.setStaleConnectionCheckEnabled(STALE_CONNECTION_CHECK.get())
.build();
CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
.setSSLStrategy(sslSessionStrategy)
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
httpClient.start();
// use httpClient...
}
private static class AllowAll implements X509HostnameVerifier
{
@Override
public void verify(String s, SSLSocket sslSocket) throws IOException
{}
@Override
public void verify(String s, X509Certificate x509Certificate) throws SSLException {}
@Override
public void verify(String s, String[] strings, String[] strings2) throws SSLException
{}
@Override
public boolean verify(String s, SSLSession sslSession)
{
return true;
}
}
}
Это решило мою проблему,
Нам нужно импортировать сертификат на локальную java. Если нет, мы могли бы получить следующее исключение.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
SSLPOKE - это инструмент, где вы можете протестировать https-соединение с вашей локальной машины.
Команда для проверки возможности подключения:
"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026) at sun.security.ssl.Handshaker.process_record(Handshaker.java:961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138) at SSLPoke.main(SSLPoke.java:31) Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) ... 15 more
keytool -import -alias brinternal -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>
сначала появится запрос «Введите пароль хранилища ключей:» changeit - пароль по умолчанию. и, наконец, запрос «Доверяйте этому сертификату? [нет]:», укажите «да», чтобы добавить сертификат в хранилище ключей.
Verfication:
C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected
JRE_HOME/bin
или JDK/JRE/bin
keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
changeit
( stackoverflow.com/a/22782035/1304830 ). Также не забудьте запустить cmd как администратор.
– Fr4nz
28 July 2016 в 14:26
Цитата из Нет больше «не удалось найти допустимый путь сертификации для запрошенной цели»
при попытке открыть SSL-соединение с хостом с помощью JSSE. Обычно это означает, что сервер использует тестовый сертификат (возможно, сгенерированный с помощью keytool), а не сертификат из известного коммерческого центра сертификации, такого как Verisign или GoDaddy. В этом случае браузеры браузера отображают диалоговые окна с предупреждением, но поскольку JSSE не может предположить, что присутствует интерактивный пользователь, он по умолчанию генерирует исключение.
Проверка сертификата - очень важная часть безопасности SSL, но я не пишу эту запись, чтобы объяснить детали. Если вас это интересует, вы можете начать с чтения видеоролика в Википедии. Я пишу эту запись, чтобы показать простой способ поговорить с этим хостом с сертификатом тестирования, если вы действительно этого хотите.
В принципе, вы хотите добавить сертификат сервера в KeyStore с вашими доверенными сертификатами
Попробуйте предоставленный там код. Это может помочь.
У вас есть два варианта: импортируйте самозаверяющий сертификат в хранилище java для каждого jvm, на котором будет запущено программное обеспечение, или попробуйте недействительную фабрику ssl:
jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
У меня была та же проблема с ошибкой сертификатов и была вызвана SNI, а у клиента http, который я использовал, не было реализовано SNI. Таким образом, обновление версии выполнило задание
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.6</version>
</dependency>
UPDATE: что перезагрузка помогла была случайной (я надеялся, что, ура!). Реальная причина проблемы заключалась в следующем: когда Gradle направлена на использование определенного хранилища ключей, это хранилище ключей должно также содержать все официальные корневые сертификаты. В противном случае он не может обращаться к библиотекам из обычных репозиториев. Я должен был сделать это:
Импортировать самозаверяющий сертификат:
keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks
Добавить официальные корневые сертификаты:
keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks
Возможно, Денон град также мешал. Возможно, стоит убить всех запущенных демонов, найденных с помощью ./gradlew --status
, если все начнет выглядеть мрачным.
ОРИГИНАЛЬНОЕ ПОЛОЖЕНИЕ:
Никто не поверит в это, я знаю. Тем не менее, если все остальное не удается, попробуйте: После перезагрузки моего Mac проблема исчезла. Grrr.
Фон: ./gradlew jar продолжал давать мне «неспособность найти допустимый путь сертификации для запрошенной цели»
Я застрял с самозаверяющим сертификатом, сохраненным из браузера, импортируется в privateKeystore.jks. Затем инструктировал Gradle работать с privateKeystore.jks:
org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks" -Djavax.net.ssl.trustStorePassword=changeit
Как уже упоминалось, это работало только после перезагрузки.
У меня была та же проблема с действительным подписанным подстановочным сертификатом от symantec.
Сначала попробуйте запустить java-приложение с помощью -Djavax.net.debug = SSL , чтобы узнать, что такое
Я закончил импорт промежуточного сертификата , который вызывал разрыв цепи сертификата.
Я загрузил отсутствующий промежуточный сертификат от symantec ( вы можете увидеть ссылку для загрузки отсутствующего сертификата в журнале рукопожатия ssl: http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer в моем случае).
И я импортировал сертификат в хранилище java. После импорта промежуточного сертификата моя подстановочная команда ssl cert наконец начала работать:
keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer
-Djavax.net.debug=ssl,handshake -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStore=our-client-certs -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=their-server-certs
– kisna
4 January 2017 в 04:26
Только для Windows выполните следующие действия: