论坛首页 Java企业应用论坛

SSL介绍与Java实例

浏览 62556 次
精华帖 (3) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2012-07-12  
阿男bluedash 写道
smallbee 写道
最近项目也在用Https,其中一个系统1是银行系统,部署在银行内部,另外一个系统2可以部署在行内也可以部署在行外。之前系统2都是行内的,所以走socket通信,现在想增加一个https通信方便行外系统2对接系统1。

后台都是java写的。要求ssl双向认证。

用jdk生成证书然后Https通信都成功了。

想请教下:
1、这个证书的一个过程是怎么样的?证书是自己做的么?然后去CA认证,还是都是从CA买的,他们帮我们认证好?
2、从上面的说法,如果想发给服务器,需要把服务器证书倒出来到客户端,让客户端信任服务器证书,然后实现通信。但是如果证书是从CA那里验证过的,是不是不需要导出到客户端这个步骤,直接配置服务器证书就可以了,验证的工作室客户端拿服务器证书去CA认证,这个认证走通信么?会连接CA服务器还是本地证书文件验证?



证书,就是用来自己证明身份的证书,你可以自己生成一个,但是没有用。为什么呢?因为数字证书必须由第三方的权威机构签名后才有效。
权威机构就那几家,你可以打开你的任何浏览器,在选项里面,找高ssl相关的配置,可以看到每个浏览器里面,都有默认的几十家权威机构的数字签名文件。
对于java环境,这些默认的机构也存在,它们的签名保存在keystore里面,我们自己生成的数字证书,都是自签名的,自己签自己。
这种默认是不被浏览器或是jvm环境接受的,原因上面说了,因为我们自己签名不算数的,“自己”这个机构不在默认的keystore里面。

所以,现在问题来了,怎么样,让客户端信任服务端这个自签名的证书呢?
答案你已经知道了,将自己的证书,导进需要信任你的证书的keystore里面。

jvm有自已默认的keystore,在java的安装目录里面,是jre/lib/security/xxx那个。
/usr/lib/jvm/jre/lib/security/cacerts
里面包含了很多第三方的权威机构的数字证书。
但是我们在做项目的时候,不想污染这个默认的库,会产生安全问题。
所以我们用keytool自己生成一个全新的keystore,其实就是一个文件,你知道的。

对于自签名的证书,肯定是不可能通过验证的
如果我们把自签名的证书导进这个cacerts里面
那么我们自己签的所有证书,就都在自己的java环境下面可以认证通过了。
但是如果你想让别人的环境下面也认你这个证书,就要在别人的环境下面把你的证书给加进信任列表
如果对方是个浏览器,就把证书导出来,让对方加进浏览器的信任列表
如果对方是java,就让对方将你的证书导入到他们的keystore

当然,如果你的证书是找Verisign签过名的,那就完全没问题了。
但是Verisign非常贵,一年好多钱,所以只有生产系统上才用。因为,我们不可能让所有的用户都把服务端自签名证书导到他们的环境里,那是不现实的。而且,浏览器会弹窗报警,说服务端提供的证书不是受信的第三方签名的,用户一看有危险就闪人了。

所以,说了这么半天,你应该明白了一个道理:SSL并不存在服务端和客户端,只存在谁需要信任谁

那么我问个问题,双向握手时,需要几个证书?单向握手时,需要几个证书?

如果服务端强制要求客户端提供证书
那么他那边必定要给你生成一个能用的证书,在他的信任列表里面
否则你自己生成的客户端证书是没有用的,必须找对方签名才可以
因为对方的环境里面不可能信任你自生成的证书

如果是双向握手,为什么需要给你两个证书?
因为除了客户端要验证服务端身份, 服务器段也要验证客户端身份, 只有允许的客户端, 才能发起请求

所以,如果服务端需要验证客户端身份,那对方必须给你一个他信任的客户端证书,
要么就是:你自己生成一个客户端证书,让对方去签名。

总之必须由对方提供,你自己生成的自签名证书,是不可能在对方的信任列表里的。
如果手里现在只有一个证书,应该有两种情况:1. 这个是服务端证书,只需要单向握 2. 需要双向握手,对方少给你一个证书

我文章中单向握手的客户端的例子
客户端不向服务端提供客户端证书
客户端只验证服务端证书
即clientWithoutCert()这个列子


理解了原理最重要
后续的问题就都不难了。

原理特别简单:你自己做张信用卡,自己签个名,去商店买东西,没人要
于是你找银行给你背书:此信用卡有效,和银行账户绑定,你四处用,就okay了
但是银行给你签名要花钱,你只是试着玩,于是你找朋友商店,让他给你签个名,你这张卡在他的店里面有效,于是,你的卡在他的店里就能用了

所以不存在谁是客户端,谁是服务端,只是看谁签名,谁信任谁,就这样。把这个印在脑子里,就特别简单。



我知道你的意思,没有客户端和服务器的问题,只有谁信任谁,因为双向认证的话,其实是服务器认证客户,客户也要认证服务器,是双方的。

我的第一个问题其实你已经回答了,证书可以自己做,然后交给CA认证。如果之后把证书配置在服务器上,如果是单向认证,客户下载证书,然后校验证书真实性(应该不是通过去CA服务器验证的,本地文件校验),通过就实现了Https通信,没有通过,使用IE则弹出对话框,如果系统对接,通信无法建立。
第二个问题:我想问的是,如果双向认证,两个系统对接,两个服务器证书都是CA认证过的,还需要相互导证书么?
我的理解是:其中一个系统1连接到另外一个系统2的时候,由于系统2得到过CA的认证,那么系统1默认信任系统2,不需要将系统2的证书导入到系统1的可信任证书里面,系统2连系统1也一样。
之前为什么要导证书,是因为证书是自己颁发的,不受信任,但是如果证书是通过CA签名验证过的,就不需要证书导来导去,这样理解对么?
0 请登录后投票
   发表时间:2012-07-12  
如果双方的证书都是经过CA签名过的,因为这些CA在默认环境下面已经是受信的,就不再需要把对方的签名文件相互导来导去了。

比如你在访问https://的网站时,你并没有把网站的证书下载并导入浏览器,因为签名机构的签名文件是在受信的默认列表里面。

但是如果你访问一个自签名的https网站,浏览器就会报警,说这个网站的证书是无效签名,问你要不要继续访问,如果要访问,就要把它那个自签名证书导入到自己的信任列表里。

所以这里面有三个东西:

1. 服务端的证书。
2, 签名机构CA的证书。
3. 客户端的证书。

单向握手时:服务端向客户端出示自己的证书

如果服务端证书是CA签名的,因为CA的证书默认受信(对于java,在jdk的security目录中的cacerts默认就有了),所以客户端不需要导入服务端证书(已经信任了),就可以通信了。

如果服务端证书是自签名的,因为自签名证书在客户端不受信,所以连接不成功,要把服务端证书导进客户端所使用的keystore中,就okay了。

双向握手过程类似,只是多了服务端要验证客户端的身份,原理是一样的。


0 请登录后投票
   发表时间:2012-07-12  
阿男bluedash 写道
如果双方的证书都是经过CA签名过的,因为这些CA在默认环境下面已经是受信的,就不再需要把对方的签名文件相互导来导去了。

比如你在访问https://的网站时,你并没有把网站的证书下载并导入浏览器,因为签名机构的签名文件是在受信的默认列表里面。

但是如果你访问一个自签名的https网站,浏览器就会报警,说这个网站的证书是无效签名,问你要不要继续访问,如果要访问,就要把它那个自签名证书导入到自己的信任列表里。

所以这里面有三个东西:

1. 服务端的证书。
2, 签名机构CA的证书。
3. 客户端的证书。

单向握手时:服务端向客户端出示自己的证书

如果服务端证书是CA签名的,因为CA的证书默认受信(对于java,在jdk的security目录中的cacerts默认就有了),所以客户端不需要导入服务端证书(已经信任了),就可以通信了。

如果服务端证书是自签名的,因为自签名证书在客户端不受信,所以连接不成功,要把服务端证书导进客户端所使用的keystore中,就okay了。

双向握手过程类似,只是多了服务端要验证客户端的身份,原理是一样的。



恩,明白了  谢谢哈
0 请登录后投票
   发表时间:2012-07-12  
正式我目前关注的内容,要好好研究一下
0 请登录后投票
   发表时间:2012-07-13  
楼主,你给的几个链接不能用啊
0 请登录后投票
   发表时间:2012-07-13  
有个问题继续请教LZ,
比如系统1和系统2对接,两个系统都是CA认证过的,要求双向认证,由于都是CA认证的,所以不存在相互导入证书的问题,可问题出来了:只要CA认证的系统都可以对接到系统1或者系统2上,可是我们现实情况下,系统1只想让自己确定的某些系统对接,如何在SSL上做文章实现明确对接?我听说有种证书链,不知道懂否,请赐教。
0 请登录后投票
   发表时间:2012-07-13  
Hi Smallbee, SSL证书的作用是证明身份(Identity),而不是认证(Authentication)。

如果希望系统1只可以某些系统连接,可以考虑使用很多种鉴权中的一种:

1. 标准的HTTP鉴权方法(JAAS)
2. Kerberos
3. 基于SAML的认证
4. Spring Security
...
按自己的实际需要选择技术方案即可。

使用SSL是无法完成Authentication和Authorization这些需求的。
0 请登录后投票
   发表时间:2012-07-13  
阿男bluedash 写道
Hi Smallbee, SSL证书的作用是证明身份(Identity),而不是认证(Authentication)。

如果希望系统1只可以某些系统连接,可以考虑使用很多种鉴权中的一种:

1. 标准的HTTP鉴权方法(JAAS)
2. Kerberos
3. 基于SAML的认证
4. Spring Security
...
按自己的实际需要选择技术方案即可。

使用SSL是无法完成Authentication和Authorization这些需求的。

好的 3q
0 请登录后投票
   发表时间:2012-08-24  
很感谢楼主。最近正好在做这个。深刻的学习了。

想请教下这个场景:
A系统,B系统(我的网站)。

我的网站(也就是B系统)会调用A系统的某些HTTPS地址,A系统也会调用B系统某些HTTPS地址,然后目前B系统还没有配置HTTPS访问。

这种情况下,是不是我们双方都要各自生成证书然后发给对方导入,同时B系统配置好tomcat的SSL访问?

目前,A系统已经发给了我一个.jks证书和证书密码,然后告知我是双向认证。 我应该怎么做呢?
0 请登录后投票
   发表时间:2012-09-20  
双向认证需要客户端也给服务端提供证书。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics