你的位置:首页 > 操作系统

[操作系统]Tomcat单向Https验证搭建,亲自实现与主流浏览器、Android/iOS移动客户端安全通信


众所周知,iOS9已经开始在联网方面默认强制使用Https替换原来的Http请求了,虽然Http和Https各有各的优势,但是总得来说,到了现在这个安全的信息时代,开发者已经离不开Https了。

网上有很多搭建Https的教程,但是比较零散,Web浏览器端和移动端具体部署也不是特别明确,如果真的用于项目中,还需要折腾一番,本人直接来个项目级别的Demo。

 

在开始之前,我总结一下keytool这个证书工具需要处理的几种常见后缀格式的意义:

jsk/keystore, 表示一个密钥库,里面可以包含多个密钥条目(证书),密钥条目(证书)还可以分私有的和信任的等,私有的一般包括私钥、公钥和密钥条目信息,信任的一般包括公钥和密钥条目信息(公钥证书)。打开密钥库需要一个密码,同时打开每个私有密钥条目也需要一个密码(但一般建议将打开私有密钥条目的密码设置跟打开密钥库密码相同,省的弄乱了,以下我的Demo演示是设置相同的),做过给安卓apk签名打包的一定能体会到这个。

csr/certreq,证书请求文件,你把这个提交给CA,CA会给你颁发cer格式的含有公钥和密钥条目信息的证书(公钥证书)给你。

cer,用于存储某个密钥条目(证书)的公钥文件,一般你提交了csr/certreq给CA后,CA会颁发给你,你也可以通过自签名的CA颁发,如果你已经有密钥条目(证书)在密钥库里,也可以从jsk/keystore中的某个密钥条目(证书)导出其公钥和密钥条目内容的证书(公钥证书)。

综上,其实最简单的理解就是密钥库就相当于SQL数据库,各种密钥条目(证书)就相当于SQL数据库表 ,一个SQL数据库表其实跟其它的表又有父子(外键)关系的,这种关系叫做密钥条目(证书)的密钥链。为了描述更加方便,以下将《密钥库》描述词叫做《证书库》,《密钥条目》描述词叫做《证书》,cer格式的公钥和密钥条目内容的证书叫做《公钥证书》。

 

接下来开始演示Demo示例:

1、生成服务器端证书库和证书:(生成服务器端证书库和证书可以有多种方式,推荐通过走第三方CA方式,这样生成的证书以后更具有保障性和安全性(尤其是对web客户端,可以启动“绿色地址栏/安全锁 地址栏显示单位名称 EV国际认证标识”等等))

1-1-1、方式一、使用keytool,生成自签名的CA证书和自签名的server证书(下面生成的CA是自签名的,当然下面生成的server也是自签名的,这些证书在浏览器上使用绝对不会出现绿条):

1.生成自签名CA:keytool -genkey -v -alias ca -keyalg RSA -keystore D:\ca_cert_lib.jks -validity 3650
2.生成服务器证书:keytool -genkey -v -alias server -keyalg RSA -keystore D:\server_cert_lib.jks -validity 365

注意证书名叫ca定义为自签名的CA证书,证书名叫server定义为服务器证书,它们分别保存在证书库路径为 D:\ca_cert_lib.jksD:\server_cert_lib.jks 中
之所以要分自签名的CA证书server服务器证书,是因为正常情况下我们的server服务器证书是需要向第三方CA申请的,第三方CA会用它的根证书给你生成一份公钥证书(这个过程叫做第三方CA给你签名),而此处就是要自导自演展示自签名的CA给server证书签名这个过程

1-1-2、用自签名的CA给server签上CA的签名(server本身也是自签名的,下面要做的相当于将server的自签名换成CA的签名,也许你会问CA的签名是谁的,CA也可以是别人的,比如如果沃通愿意给你的CA签名的话,那么CA的颁发者就是沃通,我这里的Demo演示没有权威机构给它签名,所以我这个CA就是自己给自己签名的,这个CA其实就是ROOT证书,只不过不会被任何客户端信任(如:浏览器等)而已,即用我这个CA签发的所有server服务器证书在任何浏览器上绝对不会出现绿条):

在给server签名之前,查看一下当前证书库情况,它们的确都是各自给自己签名的:
keytool -list -v -keystore D:\ca_cert_lib.jks
keytool -list -v -keystore D:\server_cert_lib.jks

现在使用自签名CA给server签名(如果你要沃通CA给你server签名,就把下面的csr交给沃通):
1.生成server的证书请求文件:keytool -certreq -alias server -keystore D:\server_cert_lib.jks > D:\server.csr (linux上:keytool -certreq -alias server -keystore <路径>/server_cert_lib.jks | tee <路径>/server.csr)
2.使用自签名的CA对server的证书请求文件进行签名颁发服务器server.cer公钥证书:keytool -gencert -alias ca -keystore D:\ca_cert_lib.jks -infile D:\server.csr -outfile D:\server.cer
3.生成自签名CA的公钥文件:keytool -export -alias ca -keystore D:\ca_cert_lib.jks -rfc -file D:\ca.cer

此时可以先查看以下ca.cer和server.cer公钥证书具体内容(注意ca.cer是自签名CA的公钥文件,其颁发者还是它自己,而server.cer是server服务器的公钥文件,其颁发者是自签名的CA,两者是有本质区别的,下面安装回复后可以看到这个区别),不过其实他们都是个Base64过的字符串:
keytool -printcert -rfc -file D:\ca.cer
keytool -printcert -rfc -file D:\server.cer

          ,以下演示使用沃通申请免费的DV SSL证书。

1-2-1、登陆沃通,申请一个免费的DV SSL证书。

1-2-3、申请完后需要验证域名,验证域名这个事就自己去搞定吧

1-2-4、上面用自签名的CA给server证书签名已经提到了如何生成csr文件,此处通过提交证书申请文件csr申请的步骤略。以下演示在线生成,即本次讲的通过沃通CA自动生成公钥证书,顺便把server服务器证书库也一并生成好并将公钥证书导入到这个证书库,此处输入的密码实际上既是server服务器证书库密码也是server服务器证书(此种方式生成的证书名字叫做1,这个1对应上面自签名CA导入的server证书)的密码

输入密码生成证书之后就可以下载沃通CA颁布给你server服务器端用的证书库和证书了,然后部署到对应的服务器程序中,本案例部署到tomcat,为了保持统一性和直观性此处将沃通CA颁发的证书库名andy5.me.jks改名为server_cert_lib.jks

一般通过此时生成的证书名字(alias)叫做:1,对应自签名CA方式中的server证书

 因此你拿到了上面的沃通颁发的证书后,你还可以继续颁发给别人,这些你颁发的证书都是可信任的,因为沃通上面的根证书一定是可信任的,不然沃通本身就是不可以信任的。

 

2、通过上面的步骤,已经得到了含有CA颁发的证书的证书库server_cert_lib.jks了,接下来,给服务器程序tomcat配置证书库(可以理解为给服务器端安装server密钥库)

2-1、在tomcat的安装目录/conf/server.中配置和启用以下port为8443的Connector

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="D:\\server_cert_lib.jks" keystorePass="s123456"
               />

 

3、接下来,要操作客户端了(这里的客户端包括多种:1是主流浏览器、2是Android、3是iOS)

3-1、先从jks格式的服务器端证书库server_cert_lib.jks导出cer格式的服务器端公钥证书server.cer。

keytool -keystore D:\server_cert_lib.jks -export -alias server -file D:\server.cer

3-2、将server.cer服务器端公钥证书导入到客户端信任证书库(这个实现不能用keytool导入了,而是要根据具体的各个客户端平台进行实现,此步骤可以理解为给客户端安装服务器端公钥证书

3-2-1、Web浏览器实现:使用浏览器安装服务器端server.cer公钥证书

3-2-1-1、IE浏览器,直接双击server.cer,然后在证书存储——将所有证书放入下列存储,选择受信任的根证书颁发机构

3-2-1-2、火狐浏览器,火狐没办法直接将来自自签名CA颁发的server.cer公钥证书导入到证书机构中,因为火狐会检查你的服务器公钥证书server.cer的最高一级颁发者是不是权威机构(权威第三方CA),不是的话,不会通过的,比如你在火狐选项——高级——证书——查看证书——服务器/证书机构:导入server.cer,会提示无法导入,因此解决方法是在不用导入server.cer,而是在服务器选项卡中添加列外地址,如果来自权威CA颁发的server.cer,则可以直接导入。

 

3-2-2-2、可以在任何地方对该服务器发起Https请求了,如果是自签名CA签发的服务器端server证书,需要忽略域名验证才能正常通信(具体看Demo代码),显然也是不安全的。

  public void testHttps(View v) {    if (mOkHttpClient == null) {      Toast.makeText(getApplicationContext(), "请先初始化客户端密钥库和服务器端公钥!", Toast.LENGTH_SHORT).show();      return;    }    mTvResult.setText("正在从 " + HTTPS_SERVER_URL + " 获取数据....");    mWvResult.loadData("", "text/html", "UTF-8");    Request request = new Request.Builder().url(HTTPS_SERVER_URL).build();    Call call = mOkHttpClient.newCall(request);    call.enqueue(new Callback() {      @Override      public void onFailure(Call call, final IOException e) {        e.printStackTrace();        runOnUiThread(new Runnable() {          @Override          public void run() {            mTvResult.setText("从 " + HTTPS_SERVER_URL + " 获取数据失败!\n" + e);          }        });      }      @Override      public void onResponse(Call call, Response response) throws IOException {        final String html = response.body().string();        runOnUiThread(new Runnable() {          @Override          public void run() {            mTvResult.setText("从 " + HTTPS_SERVER_URL + " 获取数据成功!");            mWvResult.loadData(html, "text/html", "UTF-8");          }        });      }    });  }

3-2-2-3、成功请求界面如下,软件环境:MIUI 6(Android 4.4.2) + AS 1.5.1


3-2-3-2、成功请求界面如下,软件环境:iOS 9.2.1 + Xcode 7.2.1

    

 

参考:

http://blog.csdn.net/lmj623565791/article/details/48129405

http://callistaenterprise.se/blogg/teknik/2011/11/24/creating-self-signed-certificates-for-use-on-android

 

单向Https验证Demo相关文件.7z

 

Https双向认证随笔稍后发布

 

原创随笔,转载注明出处。