SSL的新手总数。我知道我应该使用HTTPS SSL(/ TLS?)从我的客户端应用程序将数据发送到我的服务器。或者至少那是我想做的事。
我以前在Java中的实现使用了HttpURLConnection
,看起来像这样:
HttpURLConnection conn = null;
try
{
URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStream os = conn.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write(dataString);
osw.flush();
osw.close();
os.close();
conn.connect();
if(conn.getResponseCode() != 200)
throw new MyServerException();
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
StringBuilder sb = new StringBuilder();
while ((output = br.readLine()) != null) {
sb.append(output);
}
if(conn != null)
conn.disconnect();
return sb.toString();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (ProtocolException e) {
e.printStackTrace();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if(conn != null)
conn.disconnect();
}
throw new MyServerException();
......这很好用。我发现this web page哪种情况表明我需要做的就是将HttpURLConnection
切换为HttpsURLConnection
,一切都应该正常。
另一方面,在我的服务器的cPanel上,我找到了一个Lets Encrypt
部分,它使我可以将证书应用到我的服务器域。
除此之外,还设置了PEM-Encoded Certificate
和PEM-Encoded Issuer
证书。
但后来我有点难过。我是否只是假设上面的代码更新为使用HttpsURLConnection
有效?我怎么知道它的工作原理。例如,如果我从我的cPanel中删除已颁发的证书,那么上面的代码仍然有用......
自发布以来我发现的事情
如果我将urlString
设为http
它会引发异常,而如果它是https
地址则不然,那么我猜是好的
此外,这this post表明我正走在正确的轨道上,因为我没有按照那里的建议得到任何错误,并且没有人提到这种做法是错误的。
Of possible interest,它实际上指出" SSL现在称为传输层安全性(TLS),"这已经简化了事情。
This looks like a great文章。我还注意到,除了Lets Encrypt选项之外,我们还必须在cPanel上设置SSL / TLS。真有意义,最初没有看到。 更多关闭Lets Encrypt是一项免费服务,可为您提供自动使用的证书,而不是从服务提供商处购买。但是,您也可以签署自己的免费证书,但不能识别"由任何受信任的证书颁发机构(CA)。
答案 0 :(得分:1)
我通常使用像https url连接这样的方法信任任何证书,如下所示。
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new X509TrustManager[]{new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
}}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
} catch(NoSuchAlgorithmException e) {
e.printStackTrace();
} catch(KeyManagementException e) {
e.printStackTrace();
}
使用没有主机名的证书向服务器发出安全请求。
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
然后,您可以将HttpURLConnection对象作为HttpsURLConnection对象获取。
HttpURLConnection connection = null;
try
{
URL _url = new URL(url);
String scheme = _url.getProtocol();
if(scheme.equals("https")) {
connection = (HttpsURLConnection)new URL(url).openConnection();
}
}catch(...){}
答案 1 :(得分:0)
好的,我终于在一整天后彻底解决了这个问题。 Firslty SSL和TLS通常意味着同样的想法,TLS是旧SSL的替代品。接下来,要获得安全连接,您需要在服务器上安装证书。这实际上很容易通过cPanel。事实上,我建议使用Lets Encrypt,它提供持续90天的免费证书。您可以通过设置crontab作业自动续订证书服务器端,这样它们不仅是免费的,而且也是永久性的。
设置证书后,您可以使用以下代码建立安全连接和POST:
SSLContext sc = null;
HttpsURLConnection conn = null;
try {
URL httpsURL = new URL(urlString);
sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, null, new java.security.SecureRandom());
conn = (HttpsURLConnection) httpsURL.openConnection();
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStream os = conn.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write(dataString);
osw.flush();
osw.close();
os.close();
conn.connect();
if(conn.getResponseCode() != 200)
throw new MyServerException();
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
StringBuilder sb = new StringBuilder();
while ((output = br.readLine()) != null) {
sb.append(output);
}
if(conn != null)
conn.disconnect();
return sb.toString();
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (KeyManagementException e) {
e.printStackTrace();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
if(conn != null)
conn.disconnect();
throw new MyServerException();
真的很好,很容易。也许我还需要某种主机名验证器,比如@tommybee在他的回答中提到的。