5

Keytool配置 Tomcat的HTTPS双向认证 - Librarookie

 1 year ago
source link: https://www.cnblogs.com/librarookie/p/16364384.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Keytool配置 Tomcat的HTTPS双向认证

证书生成#

keytool 简介#

Keytool是一个Java数据证书的管理工具, Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中。
在keystore里,包含两种数据:

  • 密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
  • 可信任的证书实体(trusted certificate entries)——只包含公钥

我们常说的证书就是就是上面的公钥,公钥是公开给其它人使用的

  • 证书后缀解释
    • jks 是Java的keytool证书工具支持的证书私钥格式;
    • pfx 是微软支持的私钥格式(p12是pfx的新格式);
    • cer / crt 是证书的公钥格式(cer是crt证书的微软形式)
    • csr 数字证书签名请求文件(Cerificate Signing Request)

Tips:

  • .der .cer : 此证书文件是二进制格式,只含有证书信息,不包含私钥。
  • .crt : 此证书文件是二进制格式或文本格式,一般为文本格式,功能与 .der.cer 证书文件相同。
  • .pem : 此证书文件一般是文本格式,可以存放证书或私钥,或者两者都包含。 .pem 文件如果只包含私钥,一般用 .key 文件代替。
  • .pfx .p12 : 此证书文件是二进制格式,同时包含证书和私钥,且一般有密码保护。
  • .keystore .truststore : 两者本质都是keystore,都是储存密钥的容器:
    • 不过两者存放的密钥所有者不同,keystore是存储自己的公钥和私钥而,truststore是存储自己信任对象的公钥。约定通过文件名称区分类型以及用途
    • truststore 是必须的,如果我们没有显式的指定,那么java会默认指定为 $JAVA_HOME/lib/security/cacerts 这个文件
    • java 在jdk 中已经默认在 $JAVA_HOME/lib/security/cacerts 这个文件中预置了常用的证书
  • 不同语言需要的证书格式并不一致,比如说Java采用jks,.Net采用pfx和cer,Php则采用pem和cer;
  • 区别证书的不是后缀名,而是文件的格式和内容。

keytool 命令详解#

  • 密钥和证书管理工具

    -certreq            生成证书请求
    -changealias        更改条目的别名
    -delete             删除条目
    -exportcert         导出证书(简写 export)
    -genkeypair         生成密钥对(简写 genkey)
    -genseckey          生成密钥
    -gencert            根据证书请求生成证书
    -importcert         导入证书或证书链(简写 import)
    -importpass         导入口令
    -importkeystore     从其他密钥库导入一个或所有条目
    -keypasswd          更改条目的密钥口令
    -list               列出密钥库中的条目
    -printcert          打印证书内容
    -printcertreq       打印证书请求的内容
    -printcrl           打印 CRL 文件的内容
    -storepasswd        更改密钥库的存储口令
    

Tips:

  • 使用 ketytool --help 获取所有可用命令

  • 使用 keytool -command_name -help 来获取 command_name 的用法

  • -genkey         产生密钥对(genkeypair 简写);表示要创建一个新的密钥;alias和keystore缺省时,在用户主目录中创建一个”.keystore”文件,且别名为mykey,包含用户的公钥、私钥证书
    -alias          产生证书别名,和keystore关联的唯一别名,不区分大小写(默认 `mykey`)
    -keystore       指定密钥库文件的名称(默认在用户主目录创建证书库)
    -keyalg         指定密钥的算法(可选择密钥算法:`RSA`、`DSA`、`EC`,默认`DSA`)
    -keysize        指定密钥长度(与keyalg默认对应关系:`RSA=2048`、`DSA=2048`、`EC=256`)
    -sigalg         指定签名算法(MD5和 SHA1的签名算法已经不安全)
    -validity       指定证书有效期天数(默认 `90`天)
    -storepass      指定密钥库口令,推荐与keypass一致(获取keystore信息所需的密码)
    -storetype      指定密钥库的类型,可用类型为:JKS、PKCS12等。(jdk9以前,默认为JKS。自jdk9开始,默认为PKCS12)
    -keypass        指定别名条目口令(私钥的密码)
    -dname          指定证书发行者信息(其中 CN 要和服务器的域名相同,本地测试则使用localhost,其他的可以不填)
    -list           显示密钥库中的证书信息
    -v              详细输出,显示密钥库中的证书详细信息
    -file           指定导出或导出的文件名
    -export         将别名指定的证书导出到文件(exportcert 简写)
    -import         将已签名数字证书导入密钥库(importcert 简写)
    -printcert      查看导出的证书信息
    -delete         删除密钥库中某条目
    -keypasswd      修改密钥库中指定条目口令
    -storepasswd    修改keystore口令
    -ext            X.509 扩展
    
  • 所有密码长度必须大于或等于 6 位

  • keyalg 指定加密算法;可以选择的密钥算法有:RSA、DSA(默认)、EC。

  • sigalg 指定签名算法(MD5和 SHA1的签名算法已经不安全):

    • keyalg = RSA 时,签名算法有:MD5withRSA、SHA1withRSA、SHA256withRSA(默认)、SHA384withRSA、SHA512withRSA
    • keyalg = DSA 时,签名算法有:SHA1withDSA、SHA256withDSA(默认)
  • dname 表明了密钥的发行者身份(Distinguished Names)

    • CN = 域名或IP(Common Name) 注:生成服务器证书时,CN要和服务器的域名相同,本地测试则使用localhost,其他的可以不填(客户端证书无要求)
    • OU = 组织单位名称(Organization Unit)
    • O = 组织名称(Organization Name)
    • L = 城市或区域名称(Locality Name)
    • ST = 州或省份名称(State Name)
    • C = 国家的简写(Country,CN 代表中国)

创建证书#

创建秘钥库(keystore),秘钥库是存储一个或多个密钥条目的文件,每个密钥条目应该以一个别名标识,它包含密钥和证书相关信息。

  • Usage:

    keytool -genkey 
            -alias <alias> 
            -keyalg RSA 
            [-sigalg SHA256withRSA] 
            [-keysize 2048] 
            -keypass <keypasswd> 
            -keystore <keystore_file> 
            -storetype JKS|PKCS12 
            -storepass <keystore_passwd> 
            -validity 3650 
            -dname "CN=github.com,OU=github.com,Inc.,O=Github, Inc.,L=San Francisco,ST=California,C=US" 
            -ext SAN=dns:github.com,dns:www.github.com,ip:127.0.0.1 
    
  • Options:

    -genkey     产生密钥对(genkeypair 简写)
    -alias      证书别名;和keystore关联的唯一别名,这个alias通常不区分大小写(默认`mykey`)
    -keyalg     指定加密算法,RSA:非对称加密(默认`DSA`)
    -sigalg     指定签名算法,可选;
    -keysize    指定密钥长度,可选;
    -keypass    指定别名条目口令(私钥的密码)
    -storetype  生成证书类型,可用的证书库类型为:JKS、PKCS12等。
    -keystore   指定产生的密钥库的位置;
    -storepass  指定密钥库的存取口令,推荐与keypass一致
    -validity   证书有效期天数;(默认为 90天)
    -dname      表明了密钥的发行者身份(Distinguished Names)生成证书时,其中 CN 要和服务器的域名相同,本地测试则使用localhost,其他的可以不填
    -ext        X.509 扩展
    

Tips:

  • 此处需要注意:MD5和SHA1的签名算法已经不安全;
  • 如果Tomcat所在服务器的域名不是“localhost”时,浏览器会弹出警告窗口,提示用户证书与所在域不匹配。
    • 服务器证书 dname的 CN应改为对应的域名,如“www.github.com”;在本地做开发测试时,CN应填入“localhost”;
    • 客户端证书 dname的 CN可以是任意值,且不用使用 -ext扩展。

创建证书栗子#

  1. 生成服务器证书

    keytool -genkey -alias server -keyalg RSA -keypass 123456 -keystore ~/ssl/tomcat.jks [-storetype JKS] -storepass 123456 -validity 3650 -dname "CN=localhost" -ext SAN=ip:127.0.0.1

  2. 生成客户端证书,以便让服务器来验证它。为了能将证书顺利导入至IE和Firefox,证书格式应该是PKCS12(客户端的CN可以是任意值)

    keytool -genkey -alias client -keyalg RSA -keypass 123456 -keystore ~/ssl/client.p12 -storetype PKCS12 -storepass 123456 -validity 3650 -dname "CN=client"

导出证书信息#

此证书文件不包含私钥;分为自签名证书和认证证书,下面分别介绍了两中证书的生成方式

  • 认证证书与导出的服务器自签名证书作用一致,使用时取其中一种证书即可。两者主要区别为是否经证书机构认证;
  • 使用自签名证书则无需生成证书签名请求(CSR),使用认证证书则无需导出服务器自签名证书;
  • 大部分认证证书都是收费的;

导出自签名证书#

自签名证书没有经过证书认证机构进行认证,但并不影响使用,我们可以使用相应的命令对证书进行导出;

  • Usage:

    keytool -export 
            -alias <alias> 
            -keystore <keystore_file> 
            -storepass <keystore_passwd> 
            -file <file_cer>    
            [-rfc] 
    
  • Options:

    -export     执行证书导出操作(exportcert 简写)
    -alias      密钥库中的证书条目别名(jks里可以存储多对公私钥文件,通过别名指定导出的公钥证书)
    -keystore   指定密钥库文件
    -storepass  密钥库口令
    -file       导出文件的输出路径
    -rfc        使用Base64格式输出(输出pem编码格式的证书,文本格式),不适用则导出的证书为DER编码格式
    
导出证书栗子
  1. 导出服务器证书

    此处为服务器的自签名证书导出, 如果需要使用认证证书,则生成证书签名请求

    keytool -export -alias server -keystore ~/ssl/tomcat.jks -storepass 123456 -file ~/ssl/server.cer

  2. 导出客户端证书

    双向认证: 服务端信任客户端,由于不能直接将PKCS12格式的证书库导入,所以必须先把客户端证书导出为一个单独的CER文件

    keytool -export -alias client -keystore ~/ssl/client.p12 -storepass 123456 -file ~/ssl/client.cer -rfc

获取认证证书(生成证书签名请求)#

如果想得到证书认证机构的认证,则不使用上述的自签名证书,需要使用步骤导出数字证书并签发申请(Cerificate Signing Request),经证书认证机构认证并颁发后,再将认证后的证书导入本地密钥库与信任库。

  • Usage:

    keytool -certreq 
            -alias <alias> 
            -keystore <keystore_file> 
            -storepass <keystore_passwd> 
            -file <file_csr> 
    
  • Options:

    -certreq    执行证书签发申请导出操作
    -alias      密钥库中的证书条目别名
    -keystore   密钥库文件名称
    -storepass  密钥库口令
    -file       输出的csr文件路径
    
生成证书签名请求栗子
  1. 生成证书签名请求(CSR)

    keytool -certreq -alias server -keystore ~/ssl/tomcat.jks -storepass 123456 -file ~/ssl/certreq.csr

  2. 查看生成的CSR证书请求

    keytool -printcertreq -file certreq.csr

导入证书库#

双向认证: 将各自的公钥证书分别导入对方的信任库,使客户端和服务端相互信任。

  • Usage:

    keytool -import 
            [-trustcacerts] 
            -alias <alias_cer> 
            -keystore <keystore_file>
            -storepass <keystore_passwd> 
            -file <file_cer> 
    
  • Options:

    -import     执行证书导入操作(importcert 简写)
    -alias      指定导入密钥库中的证书别名(指定的条目别名不能与密钥库中已存在的条目别名重复(导入签发证书除外))
    -trustcacerts    将证书导入信任库(信任来自 cacerts 的证书)
    -keystore   密钥库名称
    -storepass  密钥库口令
    -file       输入文件名
    

导入证书栗子#

  1. 安装服务器证书(将服务器公钥证书导入客户端)

    双向认证: 客户端信任服务端: 在客户机器上双击证书文件完成导入操作(window中导入)

    • 将服务器公钥证书 server.cer 发往客户端机器 >> 双击该证书进入“证书信息”页 >> 点击【安装证书】进入“证书导入向导”首页 >> 点击【下一步】>> 选中【将所有的证书都放入下列存储】,然后单击【浏览】 >> 选择【受信任的根证书颁发机构】b并点击【确定】 >> 点击【下一步】 >> 点击【完成】。然后弹出提示【导入完成】。
    • 将客户端证书 client.p12 发往客户端机器 >> 双击该证书进入“证书导入向导”首页 >> 点击【下一步】>> 点击【下一步】>> 输入证书密码(keystore密码)并点击【下一步】 >> 点击【下一步】 >> 点击【完成】。然后弹出提示【导入完成】。
  2. 证书导入信任库(将客户端公钥证书导入信任库)

    双向认证: 服务端信任客户端:

    keytool -import -alias clientCert -keystore ~/ssl/truststore.jks -storepass 123456 -file ~/ssl/client.cer

    此步骤会生成信任证书 truststore.jks文件, 文件存放需要信任的公钥证书,如客户端证书(也可以将 keystore值改为服务器密钥库,即tomcat.jks。此时的tomcat.jks 就同时是服务的密钥库和信任库)

查看证书#

  • Usage:

    # 查看单个证书(cer | crt)
    keytool -printcert -file <cert_file> [-v|-rfc]
    
    # 查看密钥库中的证书条目
    keytool -list [-alias <alias_name>] -keystore <keystore_file> -storepass <keystore_passwd> [-v|-rfc]
    
    # 查看生成的CSR证书请求
    keytool -printcertreq -file <certreq_file>     
    
  • Options:

    -alias      密钥库中的证书条目别名;
    -keystore   指定密钥库文件;
    -storepass  密钥库口令;
    -printcert  执行证书打印命令;
    -list       缺省情况下,命令打印证书的 MD5 指纹。
        而如果指定了 -v 选项,将以可读格式打印证书,
        如果指定了 -rfc 选项,将以可打印的编码格式输出证书。
    

查看栗子证书#

  1. 查看证书信息

    keytool -printcert -file ~/ssl/client.cer [-v|-rfc]

  2. 查看密钥库

    keytool -list -keystore ~/ssl/tomcat.jks -storepass 123456 -v

  3. 查看base64的内容(即PEM编码)

    keytool -list -keystore ~/ssl/tomcat.jks -storepass 123456 -rfc

其他keytool命令#

# 删除keystore里面指定证书条目
keytool -delete -alias <alias> -keystore <keystore_file> -storepass <keystore_passwd>

# 修改条目别名
keytool -changealias -keystore <keystore_file> -alias <old_alias> -destalias <new_alias>

# 修改条目密码
keytool -keypasswd -alias <alias> -keypass <old_keypasswd> -new <new_keypasswd> -keystore <keystore_file> -storepass <keystore_passwd>

# 修改keysore密码
keytool -storepasswd -new <new_storepasswd> -keystore <keystore_file> -storepass <old_storepasswd>


# 列出信任的CA证书(查看 JVM的信任库中的证书,storepass 默认为changeit)
## 该证书文件存在于JAVA_HOME\jre\lib\security目录下,是Java系统的CA证书仓库,可以用 'alias' 来查看证书是否真的导入到JVM中
keytool -list -v [-alias clientCer] -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit

# 导入新的CA到信任证书,导入到 JRE的信任证书库
## 常出现的异常:“未找到可信任的证书”  -- 主要原因为在客户端未将服务器下发的证书导入到JVM中。
keytool -import -trustcacerts -alias clientCer -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -file ~/ssl/client.cer

Tomcat服务认证配置#

打开Tomcat_HOME/conf/server.xml,找到如下原注释内容,并修改如下:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="true" sslProtocol="TLS"
    keystoreFile="~/ssl/tomcat.jks" keystorePass="123456"
    truststoreFile="~/ssl/truststore.jks" truststorePass="123456"
/>

Tips:

  • 其中 clientAuth 指定是否需要验证客户端证书
  • false : 表示单向SSL验证,即服务端认证;
  • true : 表示强制双向SSL验证,必须验证客户端证书;
  • want : 表示可以验证客户端证书,但如果客户端没有有效证书,也不强制验证。
  • 如果设置了clientAuth="true",则需要强制验证客户端证书。可通过双击 p12 文件将证书导入至浏览器;
  • 浏览器的HTTP缺省端口为 80 , HTTPS缺省端口为 443
  • keystoreFile /keystorePass : 服务器证书文件和密码;
  • truststoreFile /truststorePass : 信任证书文件和密码;用来验证客户端的。

SSL单向证书认证配置#

  1. 创建服务器证书
  2. 导出服务器公钥证书
  3. 将服务器公钥证书导入客户端(客户端信任服务器)
  4. 配置 Tomcat
    打开Tomcat_HOME/conf/server.xml,找到如下原注释内容,并修改如下:
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS"
    keystoreFile="~/ssl/tomcat.jks" keystorePass="123456"()
/>

SSL双向证书认证配置#

  1. 创建服务器证书,创建客户端证书

  2. 导出服务器公钥证书,导出客户端公钥证书

  3. 将服务器公钥证书导入客户端(客户端信任服务器)

  4. 将客户端公钥证书导入信任库(服务器信任客户端)

  5. 配置 Tomcat,并开启双向认证():
    打开Tomcat_HOME/conf/server.xml,找到如下原注释内容,并修改如下:

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
        maxThreads="150" scheme="https" secure="true"
        clientAuth="true" sslProtocol="TLS"
        keystoreFile="~/ssl/tomcat.jks" keystorePass="123456"
        truststoreFile="~/ssl/truststore.jks" truststorePass="123456"
    />
    

配置Tomcat服务 HTTP自动跳转到 HTTPS(按需选配)#

打开Tomcat_HOME/conf/web.xml,在 与 加入如下代码:

<login-config> 
    <!-- Authorization setting for SSL --> 
    <auth-method>CLIENT-CERT</auth-method> 
    <realm-name>Client Cert Users-only Area</realm-name> 
</login-config> 
<security-constraint> 
    <!-- Authorization setting for SSL --> 
    <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> 

测试#

  1. 启动 Tomcat项目
  2. 访问 项目地址,本地配置如: https://localhost:8443/
  3. 如果遇到“不安全”的提示,可能是客户端未安装服务器证书

常见问题#

浏览器访问时提示:

  1. 此服务器无法证实它是“192.168..” - 您计算机的操作系统不信任其安全证书 。。。
    --客户端未导入服务器证书

  2. 此服务器无法证实它就是“192.168..” - 它的安全证书没有指定主题备用名称 。。。
    --生成服务器证书库未使用 -ext参数

  3. “192.168..”不接受您的登录证书,或者您可能没有提供登录证书。。。
    --Tomcat配置未指定信任证书库(truststore)

Reference


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK