是否可以使用 java ServerSocket 来接受 HTTPs 请求
Is it possible to use java ServerSocket to accept HTTPs requests
我有以下代码,可以很好地发送 HTTP 请求,但我如何转换它以支持 HTTPs 请求?
public test() throws Exception {
ServerSocket ss = new ServerSocket(32567);
Socket client = null;
while ((client = ss.accept()) != null) {
System.out.println("-- Sending --");
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String s = "<?xml version=\"1.0\" ?><root><message>test</message><status>OK</status></root>";
String output = "HTTP/1.1 200 OK\nContent-Type: text/xml; charset=UTF-8\nCache-Control: no-cache\nConnection: closed\nAccess-Control-Allow-Origin: *\n\n" + s;
System.out.println("--- RESPONSE ---\n" + output);
out.write(output);
out.flush();
out.close();
in.close();
client.close();
}
}
您使用 javax.net.ssl.SSLServerSocket
,但请注意,HTTP 服务器并不简单。您需要对 RFC 2616 和后继者有很好的了解。
你还需要知道HTTP中的行结束符是\r\n
,而不是\n
。
我使用了这段代码并且效果很好
HttpsURLConnection.setDefaultHostnameVerifier(
new HostnameVerifier() {
public boolean verify(String hostname, SSLSession sslSession) {
return true;
}
}
);
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
char[] keyPassword = "MY_PASSWORD".toCharArray();
KeyStore keystore = KeyStore.getInstance("PKCS12");;
keystore.load(this.getClass().getClassLoader().getResourceAsStream("MY_CERT.p12"), keyPassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keystore, keyPassword);
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
Enumeration aliases = keystore.aliases();
String keyAlias = "";
while (aliases.hasMoreElements()) {
keyAlias = (String) aliases.nextElement();
System.out.println("KEY FOUND: " + keyAlias);
}
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(keyManagers, null, null);
SSLServerSocketFactory sslContextFactory = (SSLServerSocketFactory) sc.getServerSocketFactory();
SSLServerSocket ssl = (SSLServerSocket) sslContextFactory.createServerSocket(32567);
ssl.setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2", "SSLv3"});
ssl.setEnabledCipherSuites(sslContextFactory.getSupportedCipherSuites());
并且证书存储在 jar 文件中。以上从 jar 文件中读取证书,而不是从命令行传入 -Djavax.net.ssl.keyStore=MY_CERT.p12 -Djavax.net.ssl.keyStorePassword=MY_PASSWORD
通过
生成您的证书
openssl req -new -newkey rsa:4096 -nodes -out MY_CERT.csr
openssl rsa -in privkey.pem -out MY_CERT.key -passin pass:MY_PASSWORD
openssl x509 -in MY_CERT.csr -out MY_CERT.crt -req -signkey MY_CERT.key -days 3650
openssl pkcs12 -export -inkey MY_CERT.key -in MY_CERT.crt -name localhost -out MY_CERT.p12 -passout pass:MY_PASSWORD -caname root
jar文件中需要的只是MY_CERT.p12(在jar文件的根目录下)
我有以下代码,可以很好地发送 HTTP 请求,但我如何转换它以支持 HTTPs 请求?
public test() throws Exception {
ServerSocket ss = new ServerSocket(32567);
Socket client = null;
while ((client = ss.accept()) != null) {
System.out.println("-- Sending --");
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String s = "<?xml version=\"1.0\" ?><root><message>test</message><status>OK</status></root>";
String output = "HTTP/1.1 200 OK\nContent-Type: text/xml; charset=UTF-8\nCache-Control: no-cache\nConnection: closed\nAccess-Control-Allow-Origin: *\n\n" + s;
System.out.println("--- RESPONSE ---\n" + output);
out.write(output);
out.flush();
out.close();
in.close();
client.close();
}
}
您使用 javax.net.ssl.SSLServerSocket
,但请注意,HTTP 服务器并不简单。您需要对 RFC 2616 和后继者有很好的了解。
你还需要知道HTTP中的行结束符是\r\n
,而不是\n
。
我使用了这段代码并且效果很好
HttpsURLConnection.setDefaultHostnameVerifier(
new HostnameVerifier() {
public boolean verify(String hostname, SSLSession sslSession) {
return true;
}
}
);
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
char[] keyPassword = "MY_PASSWORD".toCharArray();
KeyStore keystore = KeyStore.getInstance("PKCS12");;
keystore.load(this.getClass().getClassLoader().getResourceAsStream("MY_CERT.p12"), keyPassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keystore, keyPassword);
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
Enumeration aliases = keystore.aliases();
String keyAlias = "";
while (aliases.hasMoreElements()) {
keyAlias = (String) aliases.nextElement();
System.out.println("KEY FOUND: " + keyAlias);
}
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(keyManagers, null, null);
SSLServerSocketFactory sslContextFactory = (SSLServerSocketFactory) sc.getServerSocketFactory();
SSLServerSocket ssl = (SSLServerSocket) sslContextFactory.createServerSocket(32567);
ssl.setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2", "SSLv3"});
ssl.setEnabledCipherSuites(sslContextFactory.getSupportedCipherSuites());
并且证书存储在 jar 文件中。以上从 jar 文件中读取证书,而不是从命令行传入 -Djavax.net.ssl.keyStore=MY_CERT.p12 -Djavax.net.ssl.keyStorePassword=MY_PASSWORD
通过
生成您的证书openssl req -new -newkey rsa:4096 -nodes -out MY_CERT.csr
openssl rsa -in privkey.pem -out MY_CERT.key -passin pass:MY_PASSWORD
openssl x509 -in MY_CERT.csr -out MY_CERT.crt -req -signkey MY_CERT.key -days 3650
openssl pkcs12 -export -inkey MY_CERT.key -in MY_CERT.crt -name localhost -out MY_CERT.p12 -passout pass:MY_PASSWORD -caname root
jar文件中需要的只是MY_CERT.p12(在jar文件的根目录下)