“ org.neo4j.driver.v1.exceptions.ServiceUnavailableException: SSL Connection terminated while receiving data. This can happen due to network instabilities, or due to restarts of the database.”问题解决

 neo4j  “ org.neo4j.driver.v1.exceptions.ServiceUnavailableException: SSL Connection terminated while receiving data. This can happen due to network instabilities, or due to restarts of the database.”问题解决已关闭评论
4月 252017
 

使用Neo4j Java Driver连接远程机器时出现错误“Exception in thread “main” org.neo4j.driver.v1.exceptions.ServiceUnavailableException: SSL Connection terminated while receiving data. This can happen due to network instabilities, or due to restarts of the data1base.“

, 而连接本地机器localhost却可以正常。

连接driver时添加一个config参数:

Config noSSL = Config.build().withEncryptionLevel(Config.EncryptionLevel.NONE).toConfig(); 

代码测试:

pom.xml添加
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.1.2</version>

public static void main(String[] args) { //注意红色粗体部分
Config noSSL = Config.build().withEncryptionLevel(Config.EncryptionLevel.NONE).toConfig(); 
Driver driver = GraphDatabase.driver( “bolt://192.168.1.210:7687”, AuthTokens.basic( “neo4j”, “nel4j” ), noSSL );
Session session = driver.session();
session.run( “CREATE (a:Person {name: {name}, title: {title}})”, parameters( “name”, “Arthur”, “title”, “King” ) );
StatementResult result = session.run( “MATCH (a:Person) WHERE a.name = {name} ” + “RETURN a.name AS name, a.title AS title”, parameters( “name”, “Arthur” ) ); 

while ( result.hasNext() )
{
   Record record = result.next();
   System.out.println( record.get( “title” ).asString() + ” ” + record.get( “name” ).asString() );
}
session.close();
driver.close();
}

官网连接: https://neo4j.com/developer/java/

tomcat 安装配置apr

 tomcat  tomcat 安装配置apr已关闭评论
12月 302016
 

tomcat的运行模式有3种.修改他们的运行模式.3种模式的运行是否成功,可以看他的启动控制台,或者启动日志.或者登录他们的默认页面http://localhost:8080/查看其中的服务器状态。 

1)bio 

默认的模式,性能非常低下,没有经过任何优化处理和支持. 

2)nio 

利用java的异步io护理技术,no blocking IO技术. 

想运行在该模式下,直接修改server.xml里的Connector节点,修改protocol为 

 <Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol" 
	connectionTimeout="20000" 
	URIEncoding="UTF-8" 
	useBodyEncodingForURI="true" 
	enableLookups="false" 
	redirectPort="8443" /> 

启动后,就可以生效。 

3)apr 

安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能. 

必须要安装apr和native,直接启动就支持apr。下面的修改纯属多余,仅供大家扩充知识,但仍然需要安装apr和native 

如nio修改模式,修改protocol为org.apache.coyote.http11.Http11AprProtoco

tomcat如何支持apr?

需要安装apr, apr-util,   openssl, tomcat-native(tomcat-native包在tomcat目录的bin目录下就有源码的压缩包,解压这个包,注意下版本,也可以在http://tomcat.apache.org/download-native.cgi下载,并在http://tomcat.apache.org/native-doc/miscellaneous/changelog.html中查看下支持的openssl和apr版本,然后到对应的网站下载适合的版本)

1. 从网站 http://apache.spd.co.il/apr/ 中下载apr-xxx.tar.gz

tar zxvf apr-1.xx.xx.tar.gz

cd apr-xxx

./configure

make && make install

默认安装在/usr/local/apr目录下,可以通过命令行参数 –prefix 指定,建议不要改。

2. 从网站 http://apache.spd.co.il/apr/ 中下载apr-util-xxx.tar.gz

tar zxvf apr-util-xxx.tar.gz

cd apr-util-xxx

./configure –with-apr=/usr/local/apr     (此处路径就是上面俺转apr的路径)

make && make install


3.  openssl安装,其实linux版本一般都自带openssl,可以通过命令: openssl version查看版本,如果太低,可以

https://www.openssl.org/source/下载openssl-xx.tar.gz包编译安装

tar zxvf openssl-xx.tar.gz

cd openssl-xx

./config

make && make install (默认安装在/usr/local/ssl/)


4.  安装tomcat-native ,建议使用tomcat自己bin目录下的tomcat-native.tar.gz,

 解压, 

tomcat-native-1.1.27-src的版本进入jni/native目录,查看 BUILDING文件,可以有详细的说明

tomcat-native-1.2.10-src的版本直接进入native目录,查看BUILDING文件,有详细的说明

在native目录下,输入

configure –with-apr=/usr/local/apr –with-ssl=/usr/local/ssl  

其中/usr/local/apr 和 /usr/local/ssl分别是上面安装的apr和openssl目录。

安装完成有提示文字告诉你安装到的位置, 上面路径默认安装在/usr/local/apr/lib


配置tomcat,其实在BUILDING文件有说明,具体是:

Using it in Tomcat
——————

1. In <Connector> use of conf/server.xml:
   protocol=”org.apache.coyote.http11.Http11AprProtocol”
2. In bin/setenv.sh add the following:
   CATALINA_OPTS=”$CATALINA_OPTS -Djava.library.path=/usr/local/apr/lib”
   

 tomcat下没有bin/setenv.sh 文件就新建一个,并有可执行权。



启动tomcat , 看到如下信息: 

信息: Starting ProtocolHandler [“http-apr-8080”]

成功!

关于openssl配置(单向):

单向SSL的概念:

客户端向服务器发送消息,服务器接到消息后,用服务器端的密钥库中的私钥对数据进行加密,然后把加密后的数据和服务器端的公钥一起发送到客户端,客户端用服务器发送来的公钥对数据解密,然后在用传到客户端的服务器公钥对数据加密传给服务器端,服务器用私钥对数据进行解密,这就完成了客户端和服务器之间通信的安全问题,但是单向认证没有验证客户端的合法性。

 

不使用apr情况:

(1)产生密钥库
keytool -genkeypair -alias tomcat -keyalg RSA -keysize 1024 -validity 365 -keystore /usr/local/apache-tomcat-6.0.18/keystore

(2)在Connector上配置密钥库
<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
               maxThreads=”150″ scheme=”https” secure=”true”
               clientAuth=”false” sslProtocol=”TLS” keystoreFile=”/usr/local/tomcat/conf/keystore” keystorePass=”123456″/>

 

使用apr情况:

(1)产生密钥库

openssl genrsa -out rsa-private-key.pem 1024
openssl req -new -x509 -nodes -sha1 -days 365 -key rsa-private-key.pem -out self-signed-cert.pem

(2)在Connector上配置密钥库

<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
               maxThreads=”150″ scheme=”https” secure=”true”
               clientAuth=”false” sslProtocol=”TLS” 
               SSLCertificateKeyFile=”/usr/local/tomat/rsa-private-key.pem”
               SSLCertificateFile=”/usr/local/tomat/self-signed-cert.pem”/>

 

出现:

Failed to initialize end point associated with ProtocolHandler ["http-apr-8443"]
java.lang.Exception: Connector attribute SSLCertificateFile must be defined when using SSL with APR

可以将: protocol=“HTTP/1.1″修改为  protocol=”org.apache.coyote.http11.Http11Protocol”, 之修改https的端口,不要修改原来支持apr的http的protocol

TLS,SSL,HTTPS理解

 python  TLS,SSL,HTTPS理解已关闭评论
9月 102016
 

需要了解的背景知识:

  • 术语 HTTPS,SSL,TLS
  • 长连接与短连接的关系
  • 了解 CA 证书
  • 基本流程

一.术语扫盲

1.什么是SSL?

SSL(Secure Sockets Layer, 安全套接字),因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点——比如传输内容会被偷窥(嗅探)和篡改。发明 SSL 协议,就是为了解决这些问题。

2.那么什么是TLS呢?

到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。

很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

3.那么什么是HTTPS呢?

HTTPS = HTTP + SSL/TLS, 也就是 HTTP over SSL 或 HTTP over TLS.这是后面加S的由来

Untitled Image

相对于HTTP:

  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

二.长连接VS短连接

HTTP对TCP的连接使用分为:

  • 短连接
  • 长连接(又称“持久连接”,或“Keep-Alive”或“Persistent Connection”)

如果是短连接的话,针对每个HTML资源,就会针对每一个外部资源,分别发起一个个 TCP 连接。相反,如果是“长连接”的方式,浏览器也会先发起一个 TCP 连接去抓取页面。但是抓取页面之后,该 TCP 连接并不会立即关闭,而是暂时先保持着(所谓的“Keep-Alive”)。然后浏览器分析 HTML 源码之后,发现有很多外部资源,就用刚才那个 TCP 连接去抓取此页面的外部资源。

注意:

  • 在 HTTP 1.0 版本,【默认】使用的是“短连接”(那时候是 Web 诞生初期,网页相对简单,“短连接”的问题不大)
  • 在 HTTP 1.1 中,【默认】采用的是“Keep-Alive”的方式。

三.HTTPS的设计

HTTPS的设计要兼容HTTP

  • HTTPS 还是要基于 TCP 来传输
  • 单独使用一个新的协议,把 HTTP 协议包裹起来(所谓的“HTTP over SSL”,实际上是在原有的 HTTP 数据外面加了一层 SSL 的封装。HTTP 协议原有的 GET、POST 之类的机制,基本上原封不动)

关于HTTPS的性能,为了确保性能,SSL 的设计者至少要考虑如下几点:

  • 如何选择加密算法(“对称”or“非对称”)?
  • 如何兼顾 HTTP 采用的“短连接”TCP 方式?

四.简单运行过程

SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

问题:

  • 如何保证公钥不被篡改?:解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。
  • 公钥加密计算量太大,如何减少耗用的时间?解决方法:每一次对话(session),客户端和服务器端都生成一个”对话密钥”(session key),用它来加密信息。由于”对话密钥”是对称加密,所以运算速度非常快,而服务器公钥只用于加密”对话密钥”本身,这样就减少了加密运算的消耗时间。

因此,SSL/TLS协议的基本过程是这样的:

  • 客户端向服务器端索要并验证公钥。
  • 双方协商生成”对话密钥”。
  • 双方采用”对话密钥”进行加密通信。

如下图解:

Untitled Image

五.详解运行过程

如下图示:

Untitled Image

注意的是,”握手阶段”的所有通信都是明文的

1.客户端发出请求(ClientHello)

C向S提供信息如下:

  • 支持的协议版本,比如TLS 1.0版。
  • 一个客户端生成的随机数,稍后用于生成”对话密钥”。
  • 支持的加密方法,比如RSA公钥加密。
  • 支持的压缩方法。

2.服务器回应(SeverHello)

服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。服务器的回应包含以下内容。

  • 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
  • 一个服务器生成的随机数,稍后用于生成”对话密钥”。
  • 确认使用的加密方法,比如RSA公钥加密。
  • 服务器证书。

除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供”客户端证书”。

3.客户端回应

客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。

如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。

  • 一个随机数。该随机数用服务器公钥加密,防止被窃听。
  • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
  • 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。

现在总共有3个随机数,第三个又称”pre-master key”,有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自 生成 本次会话 所用的 同一把 “会话密钥”。

4.服务器的最后回应

服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的”会话密钥”。然后,向客户端最后发送下面信息。

  • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
  • 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用”会话密钥”加密内容。

Untitled Image

六.Https的劣势

不完整总结如下:

  • 对数据进行加解密决定了它比http慢
  • https协议需要到CA申请证书。

转自:http://beginman.cn/python/2016/05/27/ssh-with-python/?utm_source=tuicool&utm_medium=referral

openssl签名时报错the stateOrProvinceName field needed to be the same

 keytool, openssl, ssl  openssl签名时报错the stateOrProvinceName field needed to be the same已关闭评论
6月 162015
 

网上找到两个解决办法:

1. 找到openssl的配置文件openssl.cnf文件,修改下面节点的值为optional

stateOrProvinceName = optional 
organizationName = optional


2. stackoverflow中有提到:

openssl is encoding using UTF8STRING and keytool (Java 6) is encoding with PRINTABLESTRING.

Worked around it by changing the openssl configuration so it matches keytool..

找到openssl的配置文件openssl.cnf文件, 修改string_mask节点值为pkix

string_mask=pkix

但我自己使用第2个方法没有成功,使用第1个方法可以。

HttpClient 如何忽略证书验证访问https – ALLOW_ALL_HOSTNAME_VERIFIER

 安全  HttpClient 如何忽略证书验证访问https – ALLOW_ALL_HOSTNAME_VERIFIER已关闭评论
6月 272013
 

HttpClient 如何忽略证书验证 – ALLOW_ALL_HOSTNAME_VERIFIER

 

1。设置可以访问HTTPS

 

Function – getNewHttpClient 

 

 

Java代码  收藏代码

  1. /**  
  2.     * @Title: getNewHttpClient  
  3.     * @Description: Methods Description 
  4.     * @param @return     
  5.     * @return HttpClient  
  6.     * @throws  
  7.     */   
  8.       
  9.     private HttpClient getNewHttpClient() {  
  10.         try {  
  11.             KeyStore trustStore = KeyStore.getInstance(KeyStore  
  12.                     .getDefaultType());  
  13.             trustStore.load(nullnull);  
  14.             SSLSocketFactory sf = new SSLSocketFactory(trustStore);  
  15.             sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
  16.             HttpParams params = new BasicHttpParams();  
  17.             HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  
  18.             HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);  
  19.             SchemeRegistry registry = new SchemeRegistry();  
  20.             registry.register(new Scheme("http", PlainSocketFactory  
  21.                     .getSocketFactory(), 80));  
  22.             registry.register(new Scheme("https", sf, 443));  
  23.             ClientConnectionManager ccm = new ThreadSafeClientConnManager(  
  24.                     params, registry);  
  25.             return new DefaultHttpClient(ccm, params);  
  26.         } catch (Exception e) {  
  27.             return new DefaultHttpClient();  
  28.         }  
  29.     }  

 

2.忽略证书验证 

 

Class: SSLSocketFactory

 

 

Java代码  收藏代码

  1. import java.io.IOException;  
  2. import java.net.Socket;  
  3. import java.net.UnknownHostException;  
  4. import java.security.KeyManagementException;  
  5. import java.security.KeyStore;  
  6. import java.security.KeyStoreException;  
  7. import java.security.NoSuchAlgorithmException;  
  8. import java.security.UnrecoverableKeyException;  
  9. import java.security.cert.CertificateException;  
  10. import java.security.cert.X509Certificate;  
  11. import javax.net.ssl.SSLContext;  
  12. import javax.net.ssl.TrustManager;  
  13. import javax.net.ssl.X509TrustManager;  
  14. import org.apache.http.conn.ssl.SSLSocketFactory;  
  15.   
  16.   
  17. public class SSLSocketFactory extends SSLSocketFactory {  
  18.     /**  
  19.     * @Fields sslContext  
  20.     * @Description: Field Description 
  21.     */  
  22.     SSLContext sslContext = SSLContext.getInstance("TLS");  
  23.   
  24.     /**  
  25.     * <p>Title: </p>  
  26.     * <p>Description: </p>  
  27.     * @param truststore 
  28.     * @throws NoSuchAlgorithmException 
  29.     * @throws KeyManagementException 
  30.     * @throws KeyStoreException 
  31.     * @throws UnrecoverableKeyException  
  32.     */  
  33.     public SSLSocketFactory(KeyStore truststore)  
  34.             throws NoSuchAlgorithmException, KeyManagementException,  
  35.             KeyStoreException, UnrecoverableKeyException {  
  36.         super(truststore);  
  37.         TrustManager tm = new X509TrustManager() {  
  38.             public void checkClientTrusted(X509Certificate[] chain,  
  39.                     String authType) throws CertificateException {  
  40.             }  
  41.   
  42.             public void checkServerTrusted(X509Certificate[] chain,  
  43.                     String authType) throws CertificateException {  
  44.             }  
  45.   
  46.             public X509Certificate[] getAcceptedIssuers() {  
  47.                 return null;  
  48.             }  
  49.         };  
  50.         sslContext.init(nullnew TrustManager[] { tm }, null);  
  51.     }  
  52.   
  53.     /* (non-Javadoc) 
  54.     * <p>Title: createSocket</p>  
  55.     * <p>Description: </p>  
  56.     * @param socket 
  57.     * @param host 
  58.     * @param port 
  59.     * @param autoClose 
  60.     * @return 
  61.     * @throws IOException 
  62.     * @throws UnknownHostException  
  63.     * @see org.apache.http.conn.ssl.SSLSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)  
  64.     */  
  65.     @Override  
  66.     public Socket createSocket(Socket socket, String host, int port,  
  67.             boolean autoClose) throws IOException, UnknownHostException {  
  68.         return sslContext.getSocketFactory().createSocket(socket, host, port,  
  69.                 autoClose);  
  70.     }  
  71.   
  72.     /* (non-Javadoc) 
  73.     * <p>Title: createSocket</p>  
  74.     * <p>Description: </p>  
  75.     * @return 
  76.     * @throws IOException  
  77.     * @see org.apache.http.conn.ssl.SSLSocketFactory#createSocket()  
  78.     */  
  79.     @Override  
  80.     public Socket createSocket() throws IOException {  
  81.         return sslContext.getSocketFactory().createSocket();  
  82.     }  
  83. }  

 

 

3。调用并用HTTPS访问

 

 

Java代码  收藏代码

  1. DefaultHttpClient httpclient = (DefaultHttpClient) getNewHttpClient();  
  2.                   
  3.         try {  
  4.             //Secure Protocol implementation.    
  5.             SSLContext ctx = SSLContext.getInstance("SSL");  
  6.             //Implementation of a trust manager for X509 certificates    
  7.             X509TrustManager tm = new X509TrustManager() {  
  8.   
  9.                 public void checkClientTrusted(X509Certificate[] xcs,  
  10.                         String string) throws CertificateException {  
  11.   
  12.                 }  
  13.   
  14.                 public void checkServerTrusted(X509Certificate[] xcs,  
  15.                         String string) throws CertificateException {  
  16.                 }  
  17.   
  18.                 public X509Certificate[] getAcceptedIssuers() {  
  19.                     return null;  
  20.                 }  
  21.             };  
  22.             ctx.init(nullnew TrustManager[] { tm }, null);  
  23.             SSLSocketFactory ssf = new SSLSocketFactory(ctx);  
  24.             ClientConnectionManager ccm = httpclient.getConnectionManager();  
  25.             //register https protocol in httpclient's scheme registry    
  26.             SchemeRegistry sr = ccm.getSchemeRegistry();  
  27.             sr.register(new Scheme("https"443, ssf));  
  28.         } catch (Exception e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.   
  32.         HttpGet httpGet = new HttpGet(httpGetUrl);  
  33.         HttpResponse response = httpclient.execute(httpGet, localContext);  

 

 

 Posted by at 下午6:14  Tagged with:

Java Tomcat SSL 服务端/客户端双向认证のApache HttpClient(二)

 tomcat  Java Tomcat SSL 服务端/客户端双向认证のApache HttpClient(二)已关闭评论
5月 212013
 

转自:http://www.blogjava.net/icewee/archive/2012/06/05/379983.html

本演示例程是继Java Tomcat SSL 服务端/客户端双向认证(一),密钥库可证书的生成脚本不再重复黏贴,仅仅是用程序来代替浏览器访问服务端。

例程中使用到了Apache HttpClient库,版本为4.1.3

全部依赖库:

commons-logging-1.1.1.jar

httpclient-4.1.3.jar

httpcore-4.1.4.jar

httpmime-4.1.3.jar(上传文件使用)


在(一)中的程序包中创建一个客户端类:HttpsClient

HttpsClient.java

 

package com.icesoft.client;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

public class HttpsClient {
    
    private static final String KEY_STORE_TYPE_JKS = "jks";
    private static final String KEY_STORE_TYPE_P12 = "PKCS12";
    private static final String SCHEME_HTTPS = "https";
    private static final int HTTPS_PORT = 8443;
    private static final String HTTPS_URL = "https://127.0.0.1:8443/HttpClientSSL/sslServlet";
    private static final String KEY_STORE_CLIENT_PATH = "E:/ssl/client.p12";
    private static final String KEY_STORE_TRUST_PATH = "E:/ssl/client.truststore";
    private static final String KEY_STORE_PASSWORD = "123456";
    private static final String KEY_STORE_TRUST_PASSWORD = "123456";

    public static void main(String[] args) throws Exception {
        ssl();
    }

    
    private static void ssl() throws Exception {
        HttpClient httpClient = new DefaultHttpClient();
        try {
            KeyStore keyStore  = KeyStore.getInstance(KEY_STORE_TYPE_P12);
            KeyStore trustStore  = KeyStore.getInstance(KEY_STORE_TYPE_JKS);
            InputStream ksIn = new FileInputStream(KEY_STORE_CLIENT_PATH);
            InputStream tsIn = new FileInputStream(new File(KEY_STORE_TRUST_PATH));
            try {
                keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());
                trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray());
            }
 finally {
                try { ksIn.close(); } catch (Exception ignore) {}
                try { tsIn.close(); } catch (Exception ignore) {}
            }

            SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore, KEY_STORE_PASSWORD, trustStore);
            Scheme sch = new Scheme(SCHEME_HTTPS, HTTPS_PORT, socketFactory);
            httpClient.getConnectionManager().getSchemeRegistry().register(sch);
            HttpGet httpget = new HttpGet(HTTPS_URL);
            System.out.println("executing request" + httpget.getRequestLine());
            HttpResponse response = httpClient.execute(httpget);
            HttpEntity entity = response.getEntity();
            System.out.println("—————————————-");
            System.out.println(response.getStatusLine());
            if (entity != null{
                System.out.println("Response content length: " + entity.getContentLength());
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                String text;
                while ((text = bufferedReader.readLine()) != null{
                    System.out.println(text);
                }

                bufferedReader.close();
            }

            EntityUtils.consume(entity);
        }
 finally {
            httpClient.getConnectionManager().shutdown();
        }

    }


}



启动Tomcat,运行HttpsClient,控制台返回:



OK,和使用浏览器访问得到的结果一模一样!


全文完!

Java Tomcat SSL 服务端/客户端双向认证(一)

 tomcat  Java Tomcat SSL 服务端/客户端双向认证(一)已关闭评论
5月 212013
 

转自:http://www.blogjava.net/icewee/archive/2012/06/04/379947.html

SSL——Secure Sockets Layer



双向认证(个人理解):

客户端认证:

客户端通过浏览器访问某一网站时,如果该网站为HTTPS网站,浏览器会自动检测系统中是否存在该网站的信任证书,如果没有信任证书,浏览器一般会拒绝访问,IE会有一个继续访问的链接,但地址栏是红色,给予用户警示作用,即客户端验证服务端并不是强制性的,可以没有服务端的信任证书,当然是否继续访问完全取决于用户自己。如何去除地址栏的红色警告呢?后续会介绍导入服务端证书到浏览器的方法。



服务端认证:

服务端需要获取到客户端通过浏览器发送过来的认证证书,该证书在服务端的证书库中已存在,仅仅是个匹配过程,匹配成功即通过认证,可继续访问网站资源,反之则无法显示网页,后续有截图。



基本逻辑:

1、生成服务端密钥库并导出证书;

2、生成客户端密钥库并导出证书;

3、根据服务端密钥库生成客户端信任的证书;

4、将客户端证书导入服务端密钥库;

5、将服务端证书导入浏览器。



构建演示系统

演示环境:

JDK:1.6.0_32

Tomcat:apache-tomcat-7.0.27

开发工具:MyEclipse 10

浏览器:Internet Explorer 9



一、生成密钥库和证书

可参考以下密钥生成脚本,根据实际情况做必要的修改,其中需要注意的是:服务端的密钥库参数“CN”必须与服务端的IP地址相同,否则会报错,客户端的任意。

key.script

 

1、生成服务器证书库

keytool -validity 365 -genkey -v -alias server -keyalg RSA -keystore E:sslserver.keystore -dname "CN=127.0.0.1,OU=icesoft,O=icesoft,L=Haidian,ST=Beijing,c=cn" -storepass 123456 -keypass 123456


2、生成客户端证书库

keytool -validity 365 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore E:sslclient.p12 -dname "CN=client,OU=icesoft,O=icesoft,L=Haidian,ST=Beijing,c=cn" -storepass 123456 -keypass 123456


3、从客户端证书库中导出客户端证书

keytool -export -v -alias client -keystore E:sslclient.p12 -storetype PKCS12 -storepass 123456 -rfc -file E:sslclient.cer


4、从服务器证书库中导出服务器证书

keytool -export -v -alias server -keystore E:sslserver.keystore -storepass 123456 -rfc -file E:sslserver.cer


5、生成客户端信任证书库(由服务端证书生成的证书库)

keytool –import -v -alias server -file E:sslserver.cer -keystore E:sslclient.truststore -storepass 123456


6、将客户端证书导入到服务器证书库(使得服务器信任客户端证书)

keytool –import -v -alias client -file E:sslclient.cer -keystore E:sslserver.keystore -storepass 123456


7、查看证书库中的全部证书

keytool -list -keystore E:sslserver.keystore -storepass 123456





二、Tomat配置

使用文本编辑器编辑${catalina.base}/conf/server.xml

找到Connector port="8443"的标签,取消注释,并修改成如下:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="true" sslProtocol="TLS"
               keystoreFile="${catalina.base}/key/server.keystore" keystorePass="123456"
               truststoreFile="${catalina.base}/key/server.keystore" truststorePass="123456"/>



备注:

keystoreFile:指定服务器密钥库,可以配置成绝对路径,如“D:/key/server.keystore”,本例中是在Tomcat目录中创建了一个名称为key的文件夹,仅供参考。

keystorePass:密钥库生成时的密码

truststoreFile:受信任密钥库,和密钥库相同即可

truststorePass:受信任密钥库密码



三、建立演示项目

项目结构图:

项目名称:SSL(随意)





SSLServlet.java

package com.icesoft.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.security.cert.X509Certificate;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>
 * SSL Servlet
 * </p>
 * 
 * 
@author IceWee
 * @date 2012-6-4
 * 
@version 1.0
 
*/

public class SSLServlet extends HttpServlet {

    private static final long serialVersionUID = 1601507150278487538L;
    private static final String ATTR_CER = "javax.servlet.request.X509Certificate";
    private static final String CONTENT_TYPE = "text/plain;charset=UTF-8";
    private static final String DEFAULT_ENCODING = "UTF-8";
    private static final String SCHEME_HTTPS = "https";

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType(CONTENT_TYPE);
        response.setCharacterEncoding(DEFAULT_ENCODING);
        PrintWriter out = response.getWriter();
        X509Certificate[] certs = (X509Certificate[]) request.getAttribute(ATTR_CER);
        if (certs != null{
            int count = certs.length;
            out.println("共检测到[” + count + “]个客户端证书");
            for (int i = 0; i < count; i++) {
                out.println("客户端证书 [” + (++i) + “]: ");
                out.println("校验结果:" + verifyCertificate(certs[–i]));
                out.println("证书详细:r" + certs[i].toString());
            }

        }
 else {
            if (SCHEME_HTTPS.equalsIgnoreCase(request.getScheme())) {
                out.println("这是一个HTTPS请求,但是没有可用的客户端证书");
            }
 else {
                out.println("这不是一个HTTPS请求,因此无法获得客户端证书列表 ");
            }

        }

        out.close();
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    
    /**
     * <p>
     * 校验证书是否过期
     * </p>
     * 
     * 
@param certificate
     * 
@return
     */

    private boolean verifyCertificate(X509Certificate certificate) {
        boolean valid = true;
        try {
            certificate.checkValidity();
        }
 catch (Exception e) {
            e.printStackTrace();
            valid = false;
        }

        return valid;
    }


}



web.xml

说明:该演示项目强制使用了SSL,即普通的HTTP请求也会强制重定向为HTTPS请求,配置在最下面,可以去除,这样HTTP和HTTPS都可以访问。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns
="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation
="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
>
      <display-name>Secure Sockets Layer</display-name>    
    
    <servlet>
        <servlet-name>SSLServlet</servlet-name>
        <servlet-class>com.icesoft.servlet.SSLServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SSLServlet</servlet-name>
        <url-pattern>/sslServlet</url-pattern>
    </servlet-mapping>
    
    <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!– 强制SSL配置,即普通的请求也会重定向为SSL请求 –>  
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>SSL</web-resource-name>
            <url-pattern>/*</url-pattern><!– 全站使用SSL –>
        </web-resource-collection>
        <user-data-constraint>
            <description>SSL required</description>
            <!– CONFIDENTIAL: 要保证服务器和客户端之间传输的数据不能够被修改,且不能被第三方查看到 –>
            <!– INTEGRAL: 要保证服务器和client之间传输的数据不能够被修改 –>
            <!– NONE: 指示容器必须能够在任一的连接上提供数据。(即用HTTP或HTTPS,由客户端来决定)–>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
</web-app>





index.jsp

<%@ page language="java" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>客户端证书上传</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
</head>
<body>
<form action="${pageContext.request.contextPath}/sslServlet" method="post">
    <input type="submit"  value="提交证书"/>
</form>
</body>
</html>





四、演示及配置

发布演示项目,通过浏览器访问:http://127.0.0.1:8080/SSLhttps://127.0.0.1:8443/SSL,得到相同的结果,如图:













得到如上结果的原始是因为客户端没有通过服务端的安全认证,接下来将服务端给客户端颁发的证书导入到浏览器中:

双击“client.p12”







弹出窗口,下一步







默认,下一步







输入生成密钥时的密码“123456”,下一步







下一步







完成







成功







再次访问http://127.0.0.1:8080/SSLhttps://127.0.0.1:8443/SSL,弹出提示框:







点击确定后,IE浏览器自动阻止了继续访问,并给予警告提示,原因是浏览器中未导入该网站的可信证书











点击“继续浏览此网站”,弹出提示,点击确定







哇!鲜红的地址栏,够醒目吧!你访问的网站不安全那,亲!







点击“提交证书”按钮,返回正确结果!







可以看出,客户端并没有服务端那么严格,只要未通过验证就甭想访问,下面将服务端生成的信任证书导入到浏览器的根证书中,这样红色的地址栏就会消失了!

开始导入服务端信任证书,不能双击“server.cer”,需要手动导入到受信任的根证书机构中去。







浏览器Internet选项-内容-证书







点击“受信任的根证书颁发机构”







点击“导入”







下一步







手动选择“server.cer”,下一步













下一步







完成







点“是”









成功











可以看到我们刚刚导入的根证书







把所有浏览器窗口都关掉,再次访问网站,发现鲜红色已经逝去







点击“提交证书”按钮,一切正常了,双向认证的DEMO结束了!