博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于java的https双向认证,android上亦可用
阅读量:5770 次
发布时间:2019-06-18

本文共 7432 字,大约阅读时间需要 24 分钟。

From: http://my.oschina.net/jjface/blog/339144

概述: 客户端,浏览器或者使用http协议和服务器通信的程序。 如: 客户端通过浏览器访问某一网站时,如果该网站为HTTPS网站,浏览器会自动检测系统中是否存在该网站的信任证书, 如果没有信任证书,浏览器一般会拒绝访问,IE会有一个继续访问的链接,但地址栏是红色,给予用户警示作用, 即客户端验证服务端并不是强制性的,可以没有服务端的信任证书,当然是否继续访问完全取决于用户自己。 如果要去除地址栏的红色警告,需要导入服务端提供的证书到浏览器中。 服务器端,使用http协议提供服务的程序。 服务端需要获取到客户端通过浏览器发送过来的认证证书, 如: 该证书在服务端的证书库中已存在,仅仅是个...

 

概述:

客户端,浏览器或者使用http协议和服务器通信的程序。
如:
客户端通过浏览器访问某一网站时,如果该网站为HTTPS网站,浏览器会自动检测系统中是否存在该网站的信任证书,
如果没有信任证书,浏览器一般会拒绝访问,IE会有一个继续访问的链接,但地址栏是红色,给予用户警示作用,
即客户端验证服务端并不是强制性的,可以没有服务端的信任证书,当然是否继续访问完全取决于用户自己。
如果要去除地址栏的红色警告,需要导入服务端提供的证书到浏览器中。
服务器端,使用http协议提供服务的程序。
服务端需要获取到客户端通过浏览器发送过来的认证证书,
如:
该证书在服务端的证书库中已存在,仅仅是个匹配过程,匹配成功即通过认证,可继续访问网站资源,反之则无法显示网页。
基本逻辑:
1、生成服务端密钥库并导出证书.
2、生成客户端密钥库并导出证书.
3、根据服务端密钥库生成客户端信任的证书.
4、将客户端证书导入服务端密钥库.
5、将服务端证书导入浏览器.

源码下载地址:

生成密钥库和证书:
因使用java环境,下面使用jdk下面的keytool工具来生成相应的密钥库和证书
下面的命令是在windows 7 下面测试通过的,可以直接复制使用
1、创建目录,如d:/sslDemo
2、使用资源管理进入d:/sslDemo,按住shift+右键,弹出菜单,选择"在此处打开命令行".
3、服务器端相关操作
3.1、生成服务器证书库
keytool -validity 36500 -genkey -v -alias server -keyalg RSA -keystore server.keystore -dname "CN=www.itjoyee.com,OU=itjoyee.com,O=itjoyee.com,L=Wuhan,ST=HuBei,c=cn" -storepass 123456 -keypass 123456
注: 服务器证书库参数“CN”必须与服务端的IP地址相同,否则会报错,客户端的任意。
3.2、从服务器证书库中导出服务器证书
keytool -export -v -alias server -keystore server.keystore -storepass 123456 -rfc -file server.cer
3.3、生成客户端信任证书库(由服务端证书生成的证书库,客户端使用此证书验证服务端来源可靠)
keytool -import -v -alias server -file server.cer -keystore client.truststore -storepass 123456 -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
注:-storetype BKS 是生成上面可以识别的格式,如果不指定jdk默认生成的格式是JKS.
-provider org.bouncycastle.jce.provider.BouncyCastleProvider,需要下载jar包bcprov-jdk16-1.46.jar放到jdk1.7.0_65\jre\lib\ext\目录下.
注意需要jdk16,其他的版本android下面有版本不匹配的问题.
4、客户端相关操作
4.1、生成客户端证书库
keytool -validity 36500 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore client.p12 -dname "CN=clients.itjoyee.com,OU=jiajianfa,O=jiajianfa,L=Wuhan,ST=HuBei,c=cn" -storepass 123456 -keypass 123456
4.2、从客户端证书库中导出客户端证书
keytool -export -v -alias client -keystore client.p12 -storetype PKCS12 -storepass 123456 -rfc -file client.cer
注:客户端证书可以产生多个.
4.3、将客户端证书导入到服务器证书库(使得服务器信任客户端证书,服务器端用此验证客户端的合法性)
keytool -import -v -alias client -file client.cer -keystore server.keystore -storepass 123456
4.4、查看服务端证书中信任的客户端证书
keytool -list -keystore server.keystore -storepass 123456
5、服务器端配置
由于使用tomcat,下面使用tomcat做为实例配置.
5.1、在tomcat安装目录下新建key目录,将上面生成的server.keystore复制过去.
5.2、编辑tomcat安装目录下的conf目录下的server.xml,如:d:\sslDemo\apache-tomcat-7.0.55\conf\server.xml
找到Connector,修改如下:

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

 

注:           

port配置https访问的端口
SSLEnabled="true" 开启https服务
scheme="https"
secure="true"    开启服务端安全通信,客户端获取服务器端证书
keystoreFile="${catalina.base}/key/server.keystore" keystorePass="123456" 服务器证书库
clientAuth="true" 开启验证客户端
sslProtocol="TLS" 使用的协议
truststoreFile="${catalina.base}/key/server.keystore" truststorePass="123456" 服务器证书库(已导入客户端证书)
6、测试
由于生成证书CN配置的是www.itjoyee.com,故需要修改C:\Windows\System32\drivers\etc\hosts
添加
192.168.0.50    www.itjoyee.com
注:
192.168.0.50 为服务器的ip
启动tomcat
打开浏览器
地址栏输入 http://www.itjoyee.com:8080/
可以访问
地址栏输入https://www.itjoyee.com:8444/
访问结果,为无法显示,因为,没有使服务器端生成的信任的客户端证书
双击client.p12,输入密码,在此访问https://www.itjoyee.com:8444/
此时会有证书相关的提示,点击"确认",接着会提示网站安全证书有问题,点击继续访问,即可进入正常访问页面
7、tomcat下的服务强制使用ssl配置
已ROOT服务为例,修改D:\sslDemo\apache-tomcat-7.0.55\webapps\ROOT\WEB-INF\web.xml
添加

1
2
3
4
5
6
7
8
9
<
security-constraint
>       
    
<
web-resource-collection
>
        
<
web-resource-name 
>SSL</
web-resource-name
>  
        
<
url-pattern
>/*</
url-pattern
>
    
</
web-resource-collection
>
    
<
user-data-constraint
>
        
<
transport-guarantee
>CONFIDENTIAL</
transport-guarantee
>  
    
</
user-data-constraint
>
</
security-constraint
>

 

打开浏览器

地址栏输入 http://www.itjoyee.com:8080/会有证书相关提示
为了方便测试android下双向认证可以用,生成证书的时候把域名换成服务器的ip地址,验证才可以通过
1、android app 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
AsyncTask testTask = 
new 
AsyncTask() {
            
@Override
            
protected 
Object doInBackground(Object... params) {
                
try 
{
                    
HttpClient httpsClient = AppSslApplication.getHttpsClient(MainActivity.
this
.getBaseContext());
                    
HttpGet httpget = 
new 
HttpGet(HTTPS_URL);
                    
HttpResponse response = httpsClient.execute(httpget);
                    
HttpEntity entity = response.getEntity();
                    
Log.e(
"Response status"
, response.getStatusLine().toString());
                    
if 
(entity != 
null
) {
                        
Log.e(
"Response"
"Response content length: " 
+ entity.getContentLength());
                        
BufferedReader bufferedReader = 
new 
BufferedReader(
new 
InputStreamReader(entity.getContent()));
                        
String text;
                        
while 
((text = bufferedReader.readLine()) != 
null
) {
                            
Log.e(
"Response status"
, text);
                        
}
                        
bufferedReader.close();
                    
}
                    
httpsClient.getConnectionManager().shutdown();
                
catch 
(ClientProtocolException e) {
                    
e.printStackTrace();
                
catch 
(IllegalStateException e) {
                    
e.printStackTrace();
                
catch 
(IOException e) {
                    
e.printStackTrace();
                
}
                
return 
null
;
            
}
        
};
        
testTask.execute();
public 
class 
HttpClientSslHelper {
    
private 
static 
final 
String KEY_STORE_TYPE_BKS = 
"bks"
;
    
private 
static 
final 
String KEY_STORE_TYPE_P12 = 
"PKCS12"
;
    
private 
static 
final 
String SCHEME_HTTPS = 
"https"
;
    
private 
static 
final 
int 
HTTPS_PORT = 
8444
;
     
    
private 
static 
final 
String KEY_STORE_CLIENT_PATH = 
"client.p12"
;
    
private 
static 
final 
String KEY_STORE_TRUST_PATH = 
"client.truststore"
;
    
private 
static 
final 
String KEY_STORE_PASSWORD = 
"123456"
;
    
private 
static 
final 
String KEY_STORE_TRUST_PASSWORD = 
"123456"
;
    
private 
static 
KeyStore keyStore;
    
private 
static 
KeyStore trustStore;
    
public 
static 
HttpClient getSslHttpClient(Context pContext) {
        
HttpClient httpsClient = 
new 
DefaultHttpClient();
        
try 
{
            
// 服务器端需要验证的客户端证书
            
keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
             
            
// 客户端信任的服务器端证书
            
trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
             
            
InputStream ksIn = pContext.getResources().getAssets().open(KEY_STORE_CLIENT_PATH);
            
InputStream tsIn = pContext.getResources().getAssets().open(KEY_STORE_TRUST_PATH);
            
try 
{
                
keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());
                
trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray());
            
catch 
(Exception e) {
                
e.printStackTrace();
            
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, socketFactory, HTTPS_PORT);
            
httpsClient.getConnectionManager().getSchemeRegistry().register(sch);
        
catch 
(KeyManagementException e) {
            
e.printStackTrace();
        
catch 
(UnrecoverableKeyException e) {
            
e.printStackTrace();
        
catch 
(KeyStoreException e) {
            
e.printStackTrace();
        
catch 
(FileNotFoundException e) {
            
e.printStackTrace();
        
catch 
(NoSuchAlgorithmException e) {
            
e.printStackTrace();
        
catch 
(ClientProtocolException e) {
            
e.printStackTrace();
        
catch 
(IOException e) {
            
e.printStackTrace();
        
}
        
return 
httpsClient;
    
}
}

 

2、android浏览器实现

1.先把你的CA证书拷贝到你的SD卡里面
2.进入手机的"设置"->"位置和安全",最下面有个"从SD卡安装",就是安装证书的。
---------暂时没有实现

转载地址:http://odiux.baihongyu.com/

你可能感兴趣的文章
python2和python3同安装在Windows上,切换问题
查看>>
php加速工具xcache的安装与使用(基于LNMP环境)
查看>>
android超链接
查看>>
redhat tomcat
查看>>
统计数据库大小
查看>>
IO流的学习--文件夹下文件的复制
查看>>
第十六章:脚本化HTTP
查看>>
EXCEL表中如何让数值变成万元或亿元
查看>>
Cisco PIX防火墙的安装流程
查看>>
配置系列:ssm中applicationContext-mybatis.xml的简单配置
查看>>
mysql或者mariadb备份脚本
查看>>
extundelete恢复文件
查看>>
电池温度检测原理和示例代码
查看>>
Linux服务器性能评估与优化、监控利器---dstat应用
查看>>
hdu 2842 Chinese Rings 矩阵快速幂
查看>>
Powershell进阶学习(4) Powershell强大的利器“管道”
查看>>
关于GNU GPL
查看>>
request.getServletPath()和request.getPathInfo()用法
查看>>
nginx在响应request header时候带下划线的需要开启的选项
查看>>
Linux下DHCP服务器配置
查看>>