Java 如何处理以明文连接结束的https url
我尝试获取https url的页面内容,该url在获取输入流时引发异常Java 如何处理以明文连接结束的https url,java,https,Java,Https,我尝试获取https url的页面内容,该url在获取输入流时引发异常 String httpsURL = "https://careers.virtusa.com/"; URL myurl = new URL(httpsURL); HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection(); InputStream ins = con.getInputStream(); 例外情况如下: Exception in th
String httpsURL = "https://careers.virtusa.com/";
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
InputStream ins = con.getInputStream();
例外情况如下:
Exception in thread "main" javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.net.ssl.internal.ssl.InputRecord.handleUnknownRecord(InputRecord.java:523)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:355)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at url.JavaHttpsExample.main(JavaHttpsExample.java:18)
HttpURLConnection
和HttpsURLConnection
都失败。我尝试了org.apache.http.impl.client.CloseableHttpClient
,但得到了相同的异常。在浏览器中工作正常。我没有收到您收到的明文连接错误。我还验证了您尝试梳理的站点实际上是为HTTPS配置的。这是我得到的一个例外:
java.security.cert.CertificateException:未找到与sub.website.com匹配的主题替代DNS名称
这个问题的一个解决方案是安装一个信任所有主机的主机验证器(包括sun.website.com
)。尝试使用以下代码段将目标页面输出到Java控制台:
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
String httpsURL = "https://sub.website.com/";
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String input;
while ((input = br.readLine()) != null) {
System.out.println(input);
}
br.close();
注意:
当OP使用不同的站点时,我给出了这个答案。答案对于给定的条件是有效的,尽管此后OP可能已更改。您可以在此页面中找到有关要下载页面的证书的所有信息:
它说问题在于:
- Java 6u45:协议或密码套件不匹配
- Java 7u25:协议或密码套件不匹配
要解决此问题,您可以放松证书或将客户端配置为具有与证书匹配的协议和密码。例如,它们可以是:
协议:TLS 1.2
密码:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
如何解决和获取内容
我使用ApacheHttpComponents编写代码,它基本上信任任何源代码,不关心认证
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
它打印:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transiti ...
指定careers.virtusa.com正在使用的SSL版本。i、 e.TLSv1.2
在代码中
SSLContext sc=SSLContext.getInstance(“TLSv1.2”)
公共字符串getData(字符串URL)
{
TrustManager[]trustAllCerts=new TrustManager[]{new X509TrustManager(){
public java.security.cert.X509Certificate[]getAcceptedIssuers(){
返回null;
}
公共无效checkClientTrusted(X509Certificate[]证书,
字符串(authType){
}
公共无效checkServerTrusted(X509Certificate[]证书,
字符串(authType){
}
} };
字符串输出=”;
试一试{
//System.setProperty(“https.proxyHost”,“”);//如果使用代理,请取消注释
//System.setProperty(“https.proxyPort”,“”);//如果使用代理,请取消注释
SSLContext sc=SSLContext.getInstance(“TLSv1.2”);
sc.init(null,trustAllCerts,new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
//创建所有信任主机名验证程序
HostnameVerifier allHostsValid=新的HostnameVerifier(){
公共布尔验证(字符串主机名、SSLSession会话){
返回true;
}
};
//安装所有信任主机验证程序
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
/*
*修复结束
*/
URL=新URL(URL);
URLConnection con=url.openConnection();
InputStream ins=con.getInputStream();
InputStreamReader isr=新的InputStreamReader(ins);
BufferedReader in=新的BufferedReader(isr);
字符串输入线;
而((inputLine=in.readLine())!=null){
输出=输出+输入线;
}
系统输出打印项次(输出);
in.close();
}
捕获(例外e){
e、 printStackTrace();
}
返回输出;
}
我认为问题在于重定向(302)。最后一页是http而不是https
设置
调用第一个URL,获取位置头,再调用指定的位置。在Set cookie头和Location头的第二次调用中获取cookie。最后打开另一个URL连接,第二个重定向URL通知cookie(con.setRequestProperty(“cookie”,cookie))。
这应该行得通
HttpsURLConnection.setFollowRedirects(false);
String url = "https://<host>:443/OA_HTML/IrcVisitor";
String cookie = "";
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
con.setRequestMethod("GET");
con.connect();
// aasuming that is always a redirect // if(con.getResponseCode() == 302) {
url = con.getHeaderField("Location");
con.disconnect();
con = (HttpsURLConnection)new URL(url).openConnection();
con.setRequestMethod("GET");
con.connect();
// aasuming that is always a redirect // if(con.getResponseCode() == 302) {
url = con.getHeaderField("Location");
cookie = con.getHeaderField("Set-Cookie");
cookie = cookie.substring(0, cookie.indexOf(';'));
con = (HttpsURLConnection)new URL(url).openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Cookie", cookie);
con.setDoInput(true);
con.connect();
if(con.getResponseCode() == 200) {
//readStream(con.getInputStream());
//if you need to download something with a relative path from this page use "Content-Location" as base path
String basePath = con.getHeaderField("Content-Location");
}
HttpsURLConnection.setFollowRedirects(false);
String url=“https://:443/OA_HTML/IrcVisitor”;
字符串cookie=“”;
HttpURLConnection con=(HttpURLConnection)新URL(URL).openConnection();
con.setRequestMethod(“GET”);
con.connect();
//a始终是重定向//如果的使用(con.getResponseCode()==302){
url=con.getHeaderField(“位置”);
con.disconnect();
con=(HttpsURLConnection)新URL(URL).openConnection();
con.setRequestMethod(“GET”);
con.connect();
//a始终是重定向//如果的使用(con.getResponseCode()==302){
url=con.getHeaderField(“位置”);
cookie=con.getHeaderField(“设置cookie”);
cookie=cookie.substring(0,cookie.indexOf(';');
con=(HttpsURLConnection)新URL(URL).openConnection();
con.setRequestMethod(“GET”);
con.setRequestProperty(“Cookie”,Cookie);
con.setDoInput(真);
con.connect();
如果(con.getResponseCode()==200){
//readStream(con.getInputStream());
//如果您需要从此页面下载具有相对路径的内容,请使用“内容位置”作为基本路径
字符串basePath=con.getHeaderField(“内容位置”);
}
所有对https://careers.virtusa.com
被重定向到McAfee Web网关(代理)
如果您只是请求该地址http://203.62.173.60:443
您将收到一个握手错误
Handshake failed
The SSL handshake could not be performed.
Host: 10.4.190.60
Reason: :state 21:Application response 500 handshakefailed
因为网关需要来自受信任客户端的安全HTTP请求,该请求具有careers.virtusa.com
证书
这个问题不会出现在Web浏览器中,因为我假设virtusa的前端Web服务器会使用truste在内部重定向到Web网关
HttpsURLConnection.setFollowRedirects(false);
HttpsURLConnection.setFollowRedirects(false);
String url = "https://<host>:443/OA_HTML/IrcVisitor";
String cookie = "";
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
con.setRequestMethod("GET");
con.connect();
// aasuming that is always a redirect // if(con.getResponseCode() == 302) {
url = con.getHeaderField("Location");
con.disconnect();
con = (HttpsURLConnection)new URL(url).openConnection();
con.setRequestMethod("GET");
con.connect();
// aasuming that is always a redirect // if(con.getResponseCode() == 302) {
url = con.getHeaderField("Location");
cookie = con.getHeaderField("Set-Cookie");
cookie = cookie.substring(0, cookie.indexOf(';'));
con = (HttpsURLConnection)new URL(url).openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Cookie", cookie);
con.setDoInput(true);
con.connect();
if(con.getResponseCode() == 200) {
//readStream(con.getInputStream());
//if you need to download something with a relative path from this page use "Content-Location" as base path
String basePath = con.getHeaderField("Content-Location");
}
Request URL:https://careers.virtusa.com/
Request Method:GET
Status Code:302 Found
Remote Address:203.62.173.60:443
Handshake failed
The SSL handshake could not be performed.
Host: 10.4.190.60
Reason: :state 21:Application response 500 handshakefailed
TLS 1.2 Yes
TLS 1.1 Yes
TLS 1.0 No
SSL 3 No
SSL 2 No
new String[] { "TLSv1.1", "TLSv1.2" }
import java.io.File;
import javax.net.ssl.SSLContext;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
public class SSLTest {
public final static void main(String[] args) throws Exception {
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(new File("/tmp/careers.virtusa.com.jks"), "changeit".toCharArray(), new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1.1", "TLSv1.2" }, null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpGet httpget = new HttpGet("https://careers.virtusa.com/");
CloseableHttpResponse response = httpClient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
System.out.println(IOUtils.toString(entity.getContent()));
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpClient.close();
}
}
}
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());