需要生成一个 CA 根证书并以此签发二级证书,二级证书将作为服务端证书
服务端证书需要附加 SAN (Subject Alternative Name) (使用者可选名称) 信息
服务端证书需要附加 SAN (Subject Alternative Name) (使用者可选名称) 信息,示例如下
下载 KeyStore Explorer (一个 keytool 的 GUI 工具),其 GitHub 和官网地址如下
https://github.com/kaikramer/keystore-explorer
https://keystore-explorer.org/
个人建议去 GitHub 上下载 zip 包,虽然略微大一些,但可以免安装,解压即用
另外,以下内容均在 5.5.0 版本下截图演示
点击 create a new KeyStore
格式默认选择 pkcs #12 就行
保险起见,保存的时候 Files of Type 下拉框也选择 p12 那个,另外 File Name 需要自己加上 .p12 的后缀名(反正我这个版本不会自动加后缀)
首先需要创建一个密钥对 (Key Pair),空白处右键第一个就是了
如果是用过命令行工具的朋友应该知道签发二级证书的过程应该是 生成 key pair -> 生成 csr 请求 -> 签发并生成 cer 证书
不过 KeyStore Explorer 工具提供了一个便捷的方式,直接在 ca 密钥对上右键 -> Sign -> Sign New Key Pair 即可从生成密钥对到签发一气呵成
之后需要输入这个密钥对的密码,和之前设置的一致就行
点进来是这样的,选择使用标准模板
演示中最终填写的 SAN 值如下
现在得到了两个密钥对,server 就是带有 SAN 信息的服务端密钥对了,别忘了 Ctrl + S 保存一下
此时,我们可以像导出 ca 根证书那样导出这个 server 证书,但在 SpringBoot 中使用的话,并不需要这一步,直接把这份 test.p12 交给 SpringBoot 就好。
把这份 test.p12 放在 resources 目录下,然后在配置文件 application.properties 中这样写
#https端口号
server.port=443
#密钥库路径
server.ssl.key-store=classpath:test.p12
#密钥库密码
server.ssl.key-store-password=123456
#密钥库类型
server.ssl.keyStoreType=PKCS12
#使用的证书(密钥对)别名
server.ssl.keyAlias=server
如果之前创建密钥对的时候,没有把 密钥对的密码 填成和 密钥库密码 一致的,那就需要加一行
#密钥对密码
server.ssl.key-password=<要使用的密钥对的密码>
最后配成这样子,SpringBoot能够启动成功,应该就可以了
当然,此时直接访问 localhost ,肯定会报 SSL 错误,这是因为 server 的上级证书不被我们的浏览器信任。所以我们可以把之前导出的 ca.cer 安装到 受信任的根证书颁发机构(这个位置不能选错,否则系统不会认为这是根证书)
这个 SSL 的 demo 就传到 gitee 上面吧
为什么不用 keytool 命令行工具?
之前笔者也试过用 keytool,在参照了大量博客的情况下,也成功了。但是 keytool 的命令行环境经常需要写一堆参数,用起来的体验也不是特别好,于是在了解到 KeyStore Explorer 的存在后,我立刻被它圈粉了。不过不知道是不是笔记本设置了全局缩放的原因,这个工具的在我的电脑开着中文输入法的时候会不时抽风,但相比于敲一堆又臭又长的命令,我可能更喜欢这个 GUI 界面。
p12 和 cer 的区别?
仅个人见解,不一定准确
p12 是一个包含了公私钥对的文件,而 cer 只包含了公钥证书
2021年,证书里面的 SAN 信息有多重要?
2022-06-02 补充:其实把证书的 CN (Common Name) 字段填写正确应该也能避免 NET::ERR_CERT_COMMON_NAME_INVALID 这个问题,具体请参考 https://www.cnblogs.com/iiiiher/p/8085698.html 中的 “浏览器如何验证证书” 部分
如果使用了上面的 demo,不妨试试把配置文件中的证书别名改成 ca (server.ssl.keyAlias=ca),即使是 ca.cer 那个根证书已经加入系统根证书域的情况下,使用 Edge 96.0.1054.43 (当然,Chromium 内核的) 访问 localhost,依然会报 NET::ERR_CERT_COMMON_NAME_INVALID