Java 关于通过HTTPS SSL(/TLS?)正确发布的说明
总新手到SSL。我知道我应该使用HTTPS SSL(/TLS?)将数据从客户端应用程序发送到服务器。或者至少这是我想做的 我以前的Java实现使用了Java 关于通过HTTPS SSL(/TLS?)正确发布的说明,java,ssl-certificate,httpsurlconnection,Java,Ssl Certificate,Httpsurlconnection,总新手到SSL。我知道我应该使用HTTPS SSL(/TLS?)将数据从客户端应用程序发送到服务器。或者至少这是我想做的 我以前的Java实现使用了HttpURLConnection,看起来像这样: HttpURLConnection conn = null; try { URL url = new URL(urlString); conn = (HttpURLConnection) url.openConnection();
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();
。。。这个很好用。我发现我需要做的就是将我的HttpURLConnection
切换到HttpsURLConnection
,一切都应该正常
另一方面,在我服务器的cPanel上,我发现了一个letsnypt
部分,它使我能够将证书应用到我的服务器域
除其他事项外,设置此设置会产生PEM编码证书
和PEM编码颁发者
证书
但是我有点被难住了。我是否只是假设上面的代码更新为使用HttpsURLConnection
工作?我怎么知道它在工作。例如,如果我从cPanel中删除已颁发的证书,那么上面的代码仍然有效
发帖后我发现的事情
如果我将我的urlString
设为http
它会抛出异常,而如果它是https
地址,它不会,所以我想这很好
此外,这也表明我走的是正确的道路,因为我没有得到任何错误的建议,而且没有人提到这种方式是错误的
,它实际上指出“SSL现在被称为传输层安全性(TLS)”,这已经简化了事情
文章。我还注意到,除了Lets Encrypt选项之外,我们还必须在cPanel上设置SSL/TLS。真有道理,原来没看到更多:事实证明,Lets Encrypt是一项免费服务,它为您提供自动证书供您使用,而不是从服务提供商那里购买。不过,您也可以对自己的证书进行签名,这些证书是免费的,但不会被任何受信任的证书颁发机构(CA)识别。我通常使用如下方法使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(...){}
好的,我在整整一天之后终于解决了这个问题。Firslty SSL和TLS通常意味着相同的想法,TLS是旧SSL的替代品。接下来,要获得安全连接,您需要在服务器上安装证书。通过cPanel,这实际上非常容易。事实上,我建议使用Lets Encrypt,它提供持续90天的免费证书。通过设置crontab作业,您可以在服务器端自动续订证书,因此证书不仅是免费的,而且是永久的 设置证书后,可以使用以下代码建立安全连接并发布:
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。谢谢你的回答。这是否会在客户端和服务器之间创建安全的TLS连接?我想我明白你的意思了。例如,如果我有一个基于网络的客户端,我希望浏览器能够识别我的网页服务器是安全的(带有绿色的挂锁),那么我需要一个我实际付费的证书的唯一原因就是。但事实上,我正在处理移动和桌面应用程序,它们没有现代浏览器的警告。。。。。。所以我可以签署我自己的证书,而不必使用Lets加密或从CA购买证书?只要我有一个安全的连接,这就是最重要的。基本上,如果你有自己的http客户端,这不会有问题。我一直在使用我在android应用程序中提供的代码,但我们有一个带有公共证书的服务器。我还有一个带有我自己通过openssl生成的证书的推送客户端,它仍在工作。