前面文章说过,https中的SSL/TLS是一套协议规范。Java程序处理时,需要实现这个规范。Java提供了JSSE(Java Secure Socket Extension即Java安全套接字扩展)框架包;它规定了Java程序处理SSL/TLS协议时的API,同时Java提供了一个JSSE的默认实现SunJSSE。
一、JSSE定义了一些系统属性来配置SSL/TLS:
说明:
1、这里说的系统属性,不是操作系统属性,而是JRE系统属性。
JRE系统属性可以通过java启动参数选项-D来设置,例如:
java-Djavax.net.ssl.trustStore=yourTruststore.jks
也可以在程序编码中使用Sytem.setProperty()来设置。例如:
System.setProperty("javax.net.ssl.trustStore",“c:/test.jks”);
2、windows系统中,路径要使用正斜杠(/),不能用反斜杠(\)
3、信任库文件和密钥库文件,文件打开方式可以使用java自带的keytool工具,采用命令行方式打开,例如:使用keytool查看信任库中的证书
keytool-list -keystore test.jks
注意:查看信任库和密钥库都是使用-keystore选项
也可以使用带图形界面的Portecle工具,打开后界面如下:
4、cacert信任库文件里面的证书有很多,没必要每个证书都细看,基本上,浏览器能正常打开的https地址,这个库里面都包含了。所以,前面文章中介绍的Let’s Encrypt上申请的免费证书,java程序访问时,也是默认信任的。对于默认信任的https地址,访问时无需做特殊配置,与访问普通http地址一样。(前提是你使用的是默认的信任库)
二、信任自签名的证书
java程序发起https请求时,如果这个https请求对应的证书不是主流机构认证签名的(有个简单的判断方法,如果浏览器打开提示不安全,则说明这个证书),则访问前,需要添加信任这个证书。有两种方式添加信任证书
1、将证书导入到信任库文件中。
信任库文件可以是jre自带的cacert文件,也可以是自己制作的信任库文件。
使用自己制作的信任库文件的好处是,程序部署起来方便,只需要将信任库文件一起部署即可。
使用jre自带的cacert文件,则在部署的服务器上,要再导入一次,程序部署会有点麻烦。
注意:如果使用自己的制作的信任库文件,这时,权威机构的证书默认是没有的,也就是说,如果你的程序已经在访问其他https地址,你使用新的信任库时,也要将这些地址的证书。
2、信任所有证书。
采用这种方式相当于客户端不对证书进行校验检查,允许客户端程序访问所有https地址。做法如下:
1)新增一个实现了X509TrustManager接口的类。实现类只需要提供空的实现方法即可。
2)发起http请求前,设置默认的SSLSocketFactory,参考如下代码
注意:第一句代码中,TLS指是服务器使用的SSL/TLS的版本号,不同服务器可能不同
SSLContext sslcontext = SSLContext.getInstance("TLS");
*** ClientHello, TLSv1.2
三、常见的异常
问题原因:访问的https地址中的域名在信任库中没有找到。
解决:检查导入的证书中的域名值(CN属性)与你访问的https地址是否是同一个域名。或者证书使用的泛域名,你访问的域名在这个泛域名中也可以。
有时我们需要在本地测试自己的证书,而证书上已经写死了域名值。这种情况下,可以修改本机的hosts文件(C:\windows\system32\drivers\etc),添加一条值,将域名与本机循环IP(127.0.0.1)绑定。
领取专属 10元无门槛券
私享最新 技术干货