單向驗證:
第一步: 生成key:
keytool -genkey -alias mykey -keyalg RSA -keystore d:/key/testkey
keytool -export -file d:/key/testkey.crt -alias mykey -keystore d:/key/testkey
由於是本地測試,請修改本地host文件C:\Windows\System32\drivers\etc\host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
127.0.0.1 www.xiaochangwei.com
這樣就可以通過域名訪問了
第二步:tomcat配置
<Connector port="8448" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="D:\key\testKey" keystorePass="123456"/>
這里默認是注釋掉的 請打開,根據需要可以修改默認的端口,默認端口為8443
在這里需要注意的是,在linux等非windows環境下,會提示 找不到key 或者秘鑰過若等提示,在找不到秘鑰時tomcat無法正常啟動,秘鑰過若頁面不能正常訪問
需解決兩點,
①把上面的key加一個后綴以便非windows環境識別
②增加秘鑰的復雜度
完整配置如下:
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="/opt/apache-tomcat-7.0.64/testkey.keystone" keystorePass="123456" ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/>
第三步:發布項目
可以看見項目已經發布成功,且端口也可用,下面測試下端口情況
可以看出,都能正常訪問,證明已經部署成功。
參考資料:http://lixor.iteye.com/blog/1532655
雙向驗證
為服務器生成證書 keytool -genkey -v -alias server -keyalg RSA -keystore d:\key2\server.keystore -validity 36500 為客戶端生成證書 keytool -genkey -v -alias client -keyalg RSA -storetype PKCS12 -keystore d:\key2\client.key.p12 導入客戶端證書 讓服務器信任客戶端證書 1.先把客戶端證書到處為cer文件格式 keytool -export -alias client -keystore d:\key2\client.key.p12 -storetype PKCS12 -storepass 123456 -rfc -file d:\key2\client.key.cer 2.將客戶端cer導入到服務器證書庫 keytool -import -v -file d:\key2\client.key.cer -keystore d:\key2\server.keystore 3.查看安裝結果 keytool -list -keystore d:\key2\server.keystore 讓客戶端信任服務器證書 1.把服務器證書到處為cer文件 keytool -keystore d:\key2\server.keystore -export -alias server -file d:\key2\server.cer 2.在客戶端安裝服務器證書 選擇受信任的根證書頒發機構 配置tomcat <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" keystoreFile="D:\\key2\\server.keystore" keystorePass="123456" truststoreFile="D:\\key2\\server.keystore" truststorePass="123456" />
HTTP接口的調用說白了無非就是根據地址,先建立鏈接,然后獲取返回的信息或者發送請求數據過去,完成業務邏輯后關閉鏈接。
可以通過原生態的接口調用方式進行http接口的調用,http://www.cnblogs.com/xiaochangwei/p/5045264.html 也可以采用restful進行,
如果系統要調用的http接口眾多,請采用restful統一管理,使代碼更清晰
先說說接口調用時,怎么繞過https驗證,即別人的項目是以https方式發布的,如果是雙向驗證,則需要證書密碼等。
下面是參考別人的內容,地址:http://blog.csdn.net/noodies/article/details/17240805
import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; public class HttpsClient { static public HttpClient newHttpsClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); HttpConnectionParams.setConnectionTimeout(params, 10000); HttpConnectionParams.setSoTimeout(params, 10000); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", sf, 443)); ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); return new DefaultHttpClient(ccm, params); } catch (Exception e) { return new DefaultHttpClient(); } } private static class MySSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; sslContext.init(null, new TrustManager[] { tm }, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } }
受此啟發,我們項目中使用的是restful,則直接修改初始化的httpclient就好了
下面代碼就是restful風格進行http接口調用方式,請注意jar包的引入 RestTemplate 在spring-web.jar里面的
package com.xxx.rpc.restclient.utils; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Date; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.client.HttpClient; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; @SuppressWarnings("deprecation") public class HttpClientUtils { private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); private static String HTTP_PROTOCOL = "https://"; public static ResponseEntity<String> Execute(FrontInfo frontInfo) { HttpClient httpClient = null; try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), Integer.valueOf(frontInfo.getPort()))); registry.register(new Scheme("https", sf, Integer.valueOf(frontInfo.getPort()))); ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry); httpClient = new DefaultHttpClient(ccm); } catch (Exception e) { logger.info("httpclient創建錯誤."); } HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); httpComponentsClientHttpRequestFactory.setConnectTimeout(120*1000); httpComponentsClientHttpRequestFactory.setReadTimeout(120*1000); RestTemplate rt = new RestTemplate(httpComponentsClientHttpRequestFactory); String url = HttpClientUtils.generateUrl(frontInfo); HttpEntity<String> requestEntity = HttpClientUtils.generateHttpEntity(frontInfo); try { System.out.println("httpMethod = " + frontInfo.getHttpMethod()); System.out.println("url = " + url); System.out.println("requestEntity = " + requestEntity); ResponseEntity<String> responseEntity = rt.exchange(url, frontInfo.getHttpMethod(), requestEntity, String.class); logger.debug("responseEntity = [{}].", responseEntity); System.out.println("responseEntity = " + responseEntity); return responseEntity; } catch (Exception e) { System.out.println("info: " + e.getMessage()); logger.debug("error info: = [{}].", e.getMessage()); return generateRespWhenException(e); } }
由於是商業項目的代碼,所以僅貼一部分代碼,根據這個就可以完全掌握restful相關技術,需要解釋下的是:
① frontInfo 是一個共通的參數對象,為保證接口調用方式統一,里面有各接口需要的參數名等,如ip,prot,url,method,username 等等......
② generateUrl 是根據共通參數對象及條件生成具體的url,如 https://www.xiaochangwei.com/http/web/getuser.do?username=xiaogege&age=28
③ generateHttpEntity 是根據具體的業務需要增加一些共通的header信息
④ exchange 就是具體的執行了,返回ResponseEntity<String>,然后根據具體的業務返回,進行解析
⑤ 調用后解析返回信息大致如下,解析其中的body
JSONObject object = JSONObject.parseObject(response.getBody().toString()); JSONObject userJson = JSONObject.parseObject(object.getString("user")); String uuid = userJson.getString("id");
至此restful使用方式介紹完畢