【tomcat】HTTPS訪問配置 + restful調用遠程HTTPS繞過驗證


 

 單向驗證:

第一步: 生成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使用方式介紹完畢

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM