【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:WindowsSystem32driversetchost

# 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	estKey"  
               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:key2server.keystore -validity 36500

为客户端生成证书
keytool -genkey -v -alias client -keyalg RSA -storetype PKCS12 -keystore d:key2client.key.p12
导入客户端证书

让服务器信任客户端证书
 1.先把客户端证书到处为cer文件格式
 keytool -export -alias client -keystore d:key2client.key.p12 -storetype PKCS12 -storepass 123456 -rfc -file d:key2client.key.cer
 
 2.将客户端cer导入到服务器证书库
 keytool -import -v -file d:key2client.key.cer -keystore d:key2server.keystore
 
 3.查看安装结果
 keytool -list -keystore d:key2server.keystore
 
 让客户端信任服务器证书
 1.把服务器证书到处为cer文件
 keytool -keystore d:key2server.keystore -export -alias server -file d:key2server.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使用方式介绍完毕

原文地址:https://www.cnblogs.com/xiaochangwei/p/https_restful.html