Java 如何处理以明文连接结束的https 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

我尝试获取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 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());