我正在尝试使用基于HttpsURLConnection的实现替换基于SSLSocket的工作。当我使用包含特殊字符的有效URL时,我尝试过的每个HTTPS请求都会使用我的HttpsURLConnection实现返回状态403。同时,相同的URL使用我的SSLSocket实现返回状态200。
任何人都可以看到HTTPS请求使用SSLSocket返回200的任何原因,但是使用HttpsURLConnection返回403?
以下是 SSLSocket 实施:
import com.sun.net.ssl.internal.ssl.Provider;
import javax.net.ssl.*;
import java.io.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
public class UseSslSocket
{
public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, IOException
{
String host = "www.google.com";
String resource = "/search?q=weather";
TrustManager[] trustAllCert = new TrustManager[]
{
new X509TrustManager()
{
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType){}
public void checkServerTrusted(X509Certificate[] certs, String authType){}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCert, new SecureRandom());
Security.addProvider(new Provider());
SSLSocketFactory sslFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) sslFactory.createSocket(host, 443);
Writer streamWriter = new OutputStreamWriter(sslSocket.getOutputStream());
String rn = System.getProperty("line.separator");
streamWriter.write("GET "+ resource +" HTTP/1.1"+ rn +"Connection:close"+ rn +"Host:"+ host + rn + rn);
streamWriter.flush();
InputStreamReader streamReader = new InputStreamReader(sslSocket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(streamReader);
String response = new String();
for (String line; (line = bufferedReader.readLine()) != null; response += line + rn);
streamWriter.close();
bufferedReader.close();
sslSocket.close();
System.out.println("https://"+ host + resource +" >> "+ response.substring(0, response.indexOf(rn)));
// System.out.println(response);
}
}
以下是 HttpsURLConnection 实施:
import javax.net.ssl.*;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
public class UseUrlConnect
{
public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException, URISyntaxException, IOException
{
String host = "www.google.com";
String resource = "/search?q=weather";
TrustManager[] trustAllCerts = new TrustManager[]
{
new X509TrustManager()
{
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType){}
public void checkServerTrusted(X509Certificate[] certs, String authType){}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier()
{
public boolean verify(String hostname, SSLSession session)
{
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
URL url = new URI("https://"+ host + resource).toURL();
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
InputStreamReader streamReader = new InputStreamReader(urlConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(streamReader);
String response = new String();
for (String line; (line = bufferedReader.readLine()) != null; response += line + System.getProperty("line.separator"));
bufferedReader.close();
System.out.println(response);
}
}
PS:存在 trustAllCert 内容,以便可以接受自签名证书。