如何在http下使用https协议

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在http下使用https协议相关的知识,希望对你有一定的参考价值。

项目里需要访问其他接口,通过http/https协议。我们一般是用HttpClient类来实现具体的http/https协议接口的调用。

// Init a HttpClient
HttpClient client = new HttpClient();
String url=http://www.xxx.com/xxx;

// Init a HttpMethod
HttpMethod get = new GetMethod(url);
get.setDoAuthentication(true);
get.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(1, false));

// Call http interface
try
client.executeMethod(get);

// Handle the response from http interface
InputStream in = get.getResponseBodyAsStream();
SAXReader reader = new SAXReader();
Document doc = reader.read(in);
finally
// Release the http connection
get.releaseConnection();


以上代码在通过普通的http协议是没有问题的,但如果是https协议的话,就会有证书文件的要求了。一般情况下,是这样去做的。

// Init a HttpClient
HttpClient client = new HttpClient();
String url=https://www.xxx.com/xxx;

if (url.startsWith("https:"))
System.setProperty("javax.net.ssl.trustStore", "/.sis.cer");
System.setProperty("javax.net.ssl.trustStorePassword", "public");


于是,这里就需要事先生成一个.sis.cer的文件,生成这个文件的方法一般是先通过浏览器访问https://,导出证书文件,再用JAVA keytool command 生成证书

# $JAVA_HOME/bin/keytool -import -file sis.cer -keystore .sis.cer

但这样做,一比较麻烦,二来证书也有有效期,过了有效期之后,又需要重新生成一次证书。如果能够避开生成证书文件的方式来使用https的话,就比较好了。

还好,在最近的项目里,我们终于找到了方法。

// Init a HttpClient
HttpClient client = new HttpClient();
String url=https://www.xxx.com/xxx;

if (url.startsWith("https:"))
this.supportSSL(url, client);


用到了supportSSL(url, client)这个方法,看看这个方法是如何实现的。

private void supportSSL(String url, HttpClient client)
if(StringUtils.isBlank(url))
return;

String siteUrl = StringUtils.lowerCase(url);
if (!(siteUrl.startsWith("https")))
return;


try
setSSLProtocol(siteUrl, client);
catch (Exception e)
logger.error("setProtocol error ", e);

Security.setProperty( "ssl.SocketFactory.provider",
"com.tool.util.DummySSLSocketFactory");


private static void setSSLProtocol(String strUrl, HttpClient client) throws Exception

URL url = new URL(strUrl);
String host = url.getHost();
int port = url.getPort();

if (port <= 0)
port = 443;

ProtocolSocketFactory factory = new SSLSocketFactory();
Protocol authhttps = new Protocol("https", factory, port);
Protocol.registerProtocol("https", authhttps);
// set https protocol
client.getHostConfiguration().setHost(host, port, authhttps);


在supportSSL方法里,调用了Security.setProperty( "ssl.SocketFactory.provider",
"com.tool.util.DummySSLSocketFactory");
那么这个com.tool.util.DummySSLSocketFactory是这样的:
访问https 资源时,让httpclient接受所有ssl证书,在weblogic等容器中很有用
代码如下:
1. import java.io.IOException;
2. import java.net.InetAddress;
3. import java.net.InetSocketAddress;
4. import java.net.Socket;
5. import java.net.SocketAddress;
6. import java.net.UnknownHostException;
7. import java.security.KeyManagementException;
8. import java.security.NoSuchAlgorithmException;
9. import java.security.cert.CertificateException;
10. import java.security.cert.X509Certificate;
11.
12. import javax.net.SocketFactory;
13. import javax.net.ssl.SSLContext;
14. import javax.net.ssl.TrustManager;
15. import javax.net.ssl.X509TrustManager;
16.
17. import org.apache.commons.httpclient.ConnectTimeoutException;
18. import org.apache.commons.httpclient.params.HttpConnectionParams;
19. import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
20.
21. public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory
22. static
23. System.out.println(">>>>in MySecureProtocolSocketFactory>>");
24.
25. private SSLContext sslcontext = null;
26.
27. private SSLContext createSSLContext()
28. SSLContext sslcontext=null;
29. try
30. sslcontext = SSLContext.getInstance("SSL");
31. sslcontext.init(null, new TrustManager[]new TrustAnyTrustManager(), new java.security.SecureRandom());
32. catch (NoSuchAlgorithmException e)
33. e.printStackTrace();
34. catch (KeyManagementException e)
35. e.printStackTrace();
36.
37. return sslcontext;
38.
39.
40. private SSLContext getSSLContext()
41. if (this.sslcontext == null)
42. this.sslcontext = createSSLContext();
43.
44. return this.sslcontext;
45.
46.
47. public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
48. throws IOException, UnknownHostException
49. return getSSLContext().getSocketFactory().createSocket(
50. socket,
51. host,
52. port,
53. autoClose
54. );
55.
56.
57. public Socket createSocket(String host, int port) throws IOException,
58. UnknownHostException
59. return getSSLContext().getSocketFactory().createSocket(
60. host,
61. port
62. );
63.
64.
65.
66. public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
67. throws IOException, UnknownHostException
68. return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
69.
70.
71. public Socket createSocket(String host, int port, InetAddress localAddress,
72. int localPort, HttpConnectionParams params) throws IOException,
73. UnknownHostException, ConnectTimeoutException
74. if (params == null)
75. throw new IllegalArgumentException("Parameters may not be null");
76.
77. int timeout = params.getConnectionTimeout();
78. SocketFactory socketfactory = getSSLContext().getSocketFactory();
79. if (timeout == 0)
80. return socketfactory.createSocket(host, port, localAddress, localPort);
81. else
82. Socket socket = socketfactory.createSocket();
83. SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
84. SocketAddress remoteaddr = new InetSocketAddress(host, port);
85. socket.bind(localaddr);
86. socket.connect(remoteaddr, timeout);
87. return socket;
88.
89.
90.
91. //自定义私有类
92. private static class TrustAnyTrustManager implements X509TrustManager
93.
94. public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
95.
96.
97. public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
98.
99.
100. public X509Certificate[] getAcceptedIssuers()
101. return new X509Certificate[];
102.
103.
104.
105.

public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory
static
System.out.println(">>>>in MySecureProtocolSocketFactory>>");

private SSLContext sslcontext = null;

private SSLContext createSSLContext()
SSLContext sslcontext=null;
try
sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null, new TrustManager[]new TrustAnyTrustManager(), new java.security.SecureRandom());
catch (NoSuchAlgorithmException e)
e.printStackTrace();
catch (KeyManagementException e)
e.printStackTrace();

return sslcontext;


private SSLContext getSSLContext()
if (this.sslcontext == null)
this.sslcontext = createSSLContext();

return this.sslcontext;


public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException
return getSSLContext().getSocketFactory().createSocket(
socket,
host,
port,
autoClose
);


public Socket createSocket(String host, int port) throws IOException,
UnknownHostException
return getSSLContext().getSocketFactory().createSocket(
host,
port

然后按如下方式使用HttpClient
Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
Protocol.registerProtocol("https", myhttps);
HttpClient httpclient=new HttpClient();
参考技术A 申请SNCA的SSL证书就可以部署为HTTPS协议来对站点进行加密传输。 参考技术B 简单三步,让网站从http改造为https:
1.选择与本站适配的HTTPS(即SSL证书)
2.部署SSL证书至服务器
3.验证SSL证书状态
验证HTTPS状态可以按以下两点来检测:
能不能实现由HTTP自动跳转为HTTPS,可以多换几个不同浏览器来测试。也可以让朋友在他所属ip下真实点击操作测试,如有问题,则可能客户访问时也会出现此种情形。
查看源码是否仍存在HTTP的链接,若有,则有其他例如未能实现HTTPS的CSS、JS样式调用链接等,浏览器会提示该网址未完全加密等。

以上是关于如何在http下使用https协议的主要内容,如果未能解决你的问题,请参考以下文章

HTTP与HTTPS握手的那些事

如何同时使用http和https协议

在Tomcat下http协议转https协议

理解 HTTPS 协议

如何将网站升级为HTTPS协议?

如何将网站升级为HTTPS协议?