获取javax.net.ssl.SSLException:在使用Jsoup抓取数据时收到致命警报:protocol_版本
我正在尝试使用Jsoup从站点获取数据。 链接到该网站是 这是我获取数据的代码。 `获取javax.net.ssl.SSLException:在使用Jsoup抓取数据时收到致命警报:protocol_版本,java,ssl,web-scraping,jsoup,Java,Ssl,Web Scraping,Jsoup,我正在尝试使用Jsoup从站点获取数据。 链接到该网站是 这是我获取数据的代码。 ` 字符串url=”https://www.sos.nh.gov/corporate/soskb/SearchResults.asp?FormName=CorpNameSearch&Words=Starting&SearchStr=“+query+”&SearchType=Search”; Connection.Response-Response=Jsoup.connect(url).超时(30000) .met
字符串url=”https://www.sos.nh.gov/corporate/soskb/SearchResults.asp?FormName=CorpNameSearch&Words=Starting&SearchStr=“+query+”&SearchType=Search”;
Connection.Response-Response=Jsoup.connect(url).超时(30000)
.method(Connection.method.GET)
.userAgent(“Mozilla/5.0(Windows NT 10.0;WOW64;rv:41.0)Gecko/20100101 Firefox/41.0”)
.execute();
Document=response.parse()代码>
请告诉我这里的错误是什么。(在结束评论中,对未来的发现者进行了一些扩展)
通过实验,该站点需要协议版本TLSv1.2,尽管Java7JSSE实现了这一点,但客户端默认禁用1.2和1.1Java8默认情况下启用它们或在Java7中由于Jsoup使用HttpsURLConnection
,您可以使用系统属性https.protocols
更改启用的版本。您需要至少包括TLSv1.2
,为了获得最大的灵活性,应该使用所有当前可接受的协议https。协议=TLSv1、TLSv1.1、TLSv1.2
此外,使用所有信任TrustManager
意味着几乎所有访问您网络的恶棍都可以伪造此网站并暴露您发送的任何敏感数据。最好设置您的本地信任库,以便它接受您需要的证书和服务器,而不是伪造的证书。您希望在此处使用Java 8,因为默认情况下它支持TLSv1.2以及其他必需的密码套件
为什么不是Java7?
我用Java7(1.7.0_45)在我的机器上测试,得到了相同的错误
我激活了调试消息并强制TLSv1.2
System.setProperty("javax.net.debug", "all");
System.setProperty("https.protocols", "TLSv1.2");
然后我发现了这个新错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
最后,我去看了一些有趣的东西。
根据SSL analyzer,您的目标站点仅启用了以下密码套件:
Cipher Suites Enabled
Name (ID) Key Size (in bits)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) 128 ECDH 256-bit (P-256)
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xC030) 256 ECDH 256-bit (P-256)
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9E) 128 DH 2048-bit
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9F) 256 DH 2048-bit
有关启用所需密码套件的信息,请参阅
为什么是Java8?
另一方面,通过从Java7迁移到Java8(1.8.0_20),我成功地运行了代码,Java 8默认支持TLSV1.2,并提供了所需的密码套件
下面是Windows7上支持的Java8(1.8.0_20)密码套件(总共71个套件)的精简列表
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
...
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
片段
最后的想法:
在安全方面,始终使用最新更新版本
站点使用哪些密码?您使用哪个Java版本?站点可能需要sslv3,而您的Java版本是7。哪个版本的Java将支持它?或者任何第三方库都应该这样做?您必须检查所述web服务器支持的Ssl/tls版本。可能你要求的比它支持的要多。谷歌如何使用OpenSSL获取此信息,我相信您会在stackoverflow上找到此信息。@Marged+subbasish:另一种方式:该网站只接受TLSv1.2,默认情况下Java7客户端不接受1.2(或1.1)。由于Jsoup使用HttpsURLConnection,如果无法升级到Java8,则可以设置系统属性https.protocols=TLSv1、TLSv1.1、TLSv1.2
。此外,使用全信任TrustManager意味着几乎所有能够访问您的网络的人都可以伪造此网站并暴露您发送的任何敏感数据。@dave_Thompson_085我只是猜测,很好,您检查了详细信息。想把它变成一个答案吗?由于某种原因,这在java 7中不再起作用。你能给答案添加一个小片段吗?这样我就可以接受了。@subbasish我在帖子中添加了一个片段。
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, null, new java.security.SecureRandom());
String[] scs = sc.getSocketFactory().getSupportedCipherSuites();
Arrays.sort(scs);
for(String s : scs) {
System.out.println(s);
}
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
...
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
try {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
}
} };
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Fetch url
String url = "https://www.sos.nh.gov/corporate/soskb/SearchResults.asp?FormName=CorpNameSearch&Words=All&SearchStr=facebook&SearchType=Search";
Connection.Response response = Jsoup //
.connect(url) //
.timeout(60000) //
.method(Connection.Method.GET) //
.userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0") //
.execute();
Document document = response.parse();
System.out.println(document);
} catch (Exception e) {
e.printStackTrace();
}