前言
你有没有想过,为什么浏览器地址栏有些网站显示小锁头🔒,有些却显示"不安全"?这背后就是 HTTPS 证书在起作用。就像人需要身份证证明身份一样,网站也需要证书来证明"我是我"。
本文将用最通俗的语言,带你搞懂 HTTPS 证书的两种申请方式:适合个人/小团队的免费自动化方案,以及适合企业的正式申请流程。
一、先搞懂几个概念
1.1 HTTPS 到底在保护什么?
想象你在咖啡馆用公共 WiFi 网上银行,如果没有 HTTPS,旁边的人可以轻松看到你的账号密码。HTTPS 就像一个加密管道,让数据在传输过程中变成乱码,只有你和服务器能看懂。
1.2 证书的三要素
1.3 证书类型怎么选?
| 类型 | 长什么样 | 验证什么 | 适合谁 | 价格 |
|---|---|---|---|---|
| DV 域名验证 | 显示小锁头🔒 | 证明你拥有这个域名 | 个人博客、小网站 | 免费~几十元 |
| OV 组织验证 | 显示小锁头🔒 点击可看公司名 | 证明公司真实存在 | 企业官网 | 几百~几千元 |
| EV 扩展验证 | 显示公司名称 绿色地址栏 | 严格审核公司资质 | 银行、金融、电商 | 几千~上万元 |
二、免费方案:Let's Encrypt 自动化证书
2.1 为什么推荐 Let's Encrypt?
Let's Encrypt 是一个非营利组织,提供永久免费的 SSL 证书。虽然只有 DV 级别(域名验证),但对于个人网站、博客、小项目来说完全够用。
- ✅ 完全免费,无隐藏费用
- ✅ 自动化申请和续期
- ✅ 支持通配符证书(*.example.com)
- ✅ 所有主流浏览器信任
唯一的"缺点":证书有效期只有 90 天,但可以通过自动化脚本解决。
2.2 申请流程图解
2.3 验证方式怎么选?
2.4 首次申请:从零开始获取证书
如果你是第一次申请 Let's Encrypt 证书,需要先安装 acme.sh 客户端,然后完成首次申请。以下是完整步骤:
步骤一:安装 acme.sh
# 在线安装(推荐)
curl https://get.acme.sh | sh -s email=your-email@example.com
# 或者使用 wget
wget -O - https://get.acme.sh | sh -s email=your-email@example.com
# 安装后重新加载 shell 环境
source ~/.bashrc
# 验证安装
acme.sh --version
步骤二:选择验证方式申请证书
方式A:HTTP-01 验证(最简单,适合单域名)
# 确保你的网站可以通过 HTTP 访问
# acme.sh 会自动在网站根目录放置验证文件
# 申请证书(自动模式)
acme.sh --issue -d example.com --webroot /var/www/html
# 如果使用 nginx,可以自动配置
acme.sh --issue -d example.com --nginx
# 申请多个单域名证书
acme.sh --issue -d example.com -d www.example.com --webroot /var/www/html
方式B:DNS-01 验证(支持通配符)
# 手动 DNS 模式(需要手动添加 TXT 记录)
acme.sh --issue -d '*.example.com' -d example.com --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
# 执行后会输出类似内容:
# Domain: '_acme-challenge.example.com'
# TXT value: 'aBcDeFgHiJkLmNoPqRsTuVwXyZ123456'
#
# 请将此 TXT 记录添加到你的 DNS 解析
# 添加 DNS 记录后,继续验证
acme.sh --renew -d '*.example.com' -d example.com --yes-I-know-dns-manual-mode-enough-go-ahead-please
方式C:自动 DNS API(推荐,全自动)
# 如果你使用阿里云 DNS
export Ali_Key="your_access_key"
export Ali_Secret="your_access_secret"
acme.sh --issue -d '*.example.com' -d example.com --dns dns_ali
# 如果你使用腾讯云 DNS
export Tencent_SecretId="your_secret_id"
export Tencent_SecretKey="your_secret_key"
acme.sh --issue -d '*.example.com' -d example.com --dns dns_tencent
# 如果你使用 Cloudflare
export CF_Key="your_api_key"
export CF_Email="your_email@example.com"
acme.sh --issue -d '*.example.com' -d example.com --dns dns_cf
步骤三:安装证书到服务器
# 安装证书到 nginx
acme.sh --install-cert -d example.com \
--cert-file /etc/nginx/ssl/cert.pem \
--key-file /etc/nginx/ssl/key.pem \
--fullchain-file /etc/nginx/ssl/fullchain.pem \
--reloadcmd "nginx -s reload"
# 安装通配符证书
acme.sh --install-cert -d '*.example.com' \
--cert-file /etc/nginx/ssl/wildcard.crt \
--key-file /etc/nginx/ssl/wildcard.key \
--fullchain-file /etc/nginx/ssl/wildcard.fullchain.crt \
--reloadcmd "nginx -s reload"
步骤四:配置 Nginx 使用证书
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# SSL 优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# HSTS
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
# 你的网站配置
}
}
# HTTP 跳转 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
2.5 自动续期:让证书永不过期
Let's Encrypt 证书有效期只有 90 天,但 acme.sh 会自动设置续期任务。你也可以手动管理续期:
# 查看已安装的证书
acme.sh --list
# 手动续期某个证书
acme.sh --renew -d example.com
# 强制续期(忽略有效期检查)
acme.sh --renew -d example.com --force
# 查看自动续期任务
crontab -l | grep acme
以下是一个生产环境使用的完整续期脚本:
#!/bin/bash
# ============================================================
# Let's Encrypt 通配符证书续期脚本
# 域名: *.example.com + example.com
# ============================================================
set -e # 遇错即停
# 配置
ACME="/root/.acme.sh/acme.sh"
CERT_DIR="/etc/nginx"
CERT_FILE="${CERT_DIR}/wildcard.crt"
KEY_FILE="${CERT_DIR}/wildcard.key"
# 是否强制续期
FORCE=""
[ "$1" = "--force" ] && FORCE="--force"
echo "========================================"
echo " Let's Encrypt 通配符证书续期"
echo "========================================"
# 检查当前证书状态
echo "[检查] 当前证书状态:"
openssl x509 -in ${CERT_FILE} -noout -subject -dates 2>/dev/null || echo " 未找到现有证书"
# 智能判断是否需要续期(30天内过期才续)
if [ -z "$FORCE" ] && [ -f "$CERT_FILE" ]; then
if openssl x509 -in ${CERT_FILE} -noout -checkend 2592000 >/dev/null 2>&1; then
echo "证书有效期还有30天以上,无需续期。"
echo "如需强制续期: bash $0 --force"
exit 0
fi
echo "证书将在30天内过期,开始续期..."
fi
# 申请/续期证书
if ${ACME} --renew -d '*.example.com' -d 'example.com' \
--yes-I-know-dns-manual-mode-enough-go-ahead-please \
--server letsencrypt ${FORCE} 2>&1; then
# 安装证书
echo "[安装] 复制证书到nginx目录..."
cp /root/.acme.sh/*.example.com_ecc/fullchain.cer ${CERT_FILE}
cp /root/.acme.sh/*.example.com_ecc/*.example.com.key ${KEY_FILE}
chmod 644 ${CERT_FILE}
chmod 600 ${KEY_FILE} # 私钥权限要严格
# 重载nginx
nginx -t && nginx -s reload
echo "[完成] 新证书信息:"
openssl x509 -in ${CERT_FILE} -noout -subject -dates
echo "续期成功!"
else
# 需要更新DNS验证
echo "============================================"
echo " 需要更新DNS TXT记录!"
echo "============================================"
echo "1. 登录DNS服务商管理后台"
echo "2. 更新 _acme-challenge 的TXT记录值"
echo "3. 等待1-2分钟DNS生效"
echo "4. 验证: dig TXT _acme-challenge.example.com"
echo "5. 重新运行: bash $0 --force"
exit 1
fi
2.5 设置自动续期定时任务
# 编辑 crontab
crontab -e
# 添加以下内容(每月1号凌晨3点检查续期)
0 3 1 * * /root/web/script/renew_cert.sh >> /var/log/cert-renew.log 2>&1
三、企业方案:CSR 证书申请流程
3.1 什么时候需要走企业流程?
以下情况需要使用企业级证书申请流程:
- 🏢 公司内部 PKI 系统,需要提交 CSR 给安全团队
- 🏦 金融、医疗等行业,需要 OV/EV 级别证书
- 📋 合规要求,证书需要正式审批流程
- 🔐 需要证书显示公司名称(OV/EV 特性)
3.2 CSR 是什么?
CSR(Certificate Signing Request)证书签名请求,就像一份"申请书",包含:
- 你的公钥
- 域名信息(CN 和 SAN)
- 组织信息(公司名、部门、城市等)
私钥你自己保留,CSR 提交给 CA,CA 验证后用它的私钥签名,返回正式证书。
3.3 企业证书申请流程图
3.4 首次申请:生成 CSR 并提交
企业级证书申请的第一步是生成 CSR(证书签名请求)。CSR 包含你的公钥和身份信息,提交给 CA 后,CA 会验证并签发证书。
步骤一:准备申请信息
在生成 CSR 之前,需要准备以下信息:
| 字段 | 说明 | 示例 |
|---|---|---|
| C (Country) | 国家代码(两位) | CN、US、DE |
| S (State) | 省/州 | Beijing、Shanghai |
| L (Locality) | 城市 | Beijing、Shenzhen |
| O (Organization) | 公司/组织名称 | Your Company Ltd |
| OU (Organizational Unit) | 部门 | IT Department |
| CN (Common Name) | 主域名 | portal.example.com |
| SAN (Subject Alternative Name) | 所有需要覆盖的域名 | 多个域名列表 |
步骤二:生成密钥对和 CSR
以下是完整的 CSR 生成脚本:
#!/bin/bash
# ============================================================
# 企业级证书申请脚本 - CSR 生成
# ============================================================
# ========== 配置区域 ==========
PASSWORD="your_secure_password" # 密钥库密码(妥善保管)
DOMAIN_NAME="example.com" # 主域名
JKS_FILE="${DOMAIN_NAME}.jks" # Java KeyStore
PFX_FILE="${DOMAIN_NAME}.pfx" # PKCS#12 格式
KEY_FILE="${DOMAIN_NAME}.key" # PEM 私钥
CSR_FILE="${DOMAIN_NAME}.csr" # 证书签名请求
CERT_ALIAS="server_cert" # 证书别名
# 证书主题信息(根据实际情况修改)
CN_NAME="portal.example.com" # 主域名(Common Name)
# SAN 扩展 - 证书覆盖的所有域名
SAN_LIST="dns:portal.example.com,dns:portal.qa.example.com,dns:portal.dev.example.com,dns:api.example.com"
# ========== 步骤1:生成密钥对 ==========
echo ">>> 生成 4096 位 RSA 密钥对..."
keytool -genkey \
-alias $CERT_ALIAS \
-keyalg RSA \
-keysize 4096 \
-keystore $JKS_FILE \
-keypass $PASSWORD \
-storepass $PASSWORD \
-ext san=$SAN_LIST \
-dname "C=CN,S=Beijing,L=Beijing,O=YourCompany,OU=IT,CN=$CN_NAME"
# ========== 步骤2:转换为 PKCS#12 格式 ==========
echo ">>> 转换为 PKCS#12 格式..."
keytool -v -importkeystore \
-srckeystore $JKS_FILE \
-srcstoretype jks \
-srcstorepass $PASSWORD \
-destkeystore $PFX_FILE \
-deststoretype pkcs12 \
-deststorepass $PASSWORD \
-destkeypass $PASSWORD
# ========== 步骤3:提取 PEM 私钥 ==========
echo ">>> 提取 PEM 格式私钥..."
openssl pkcs12 \
-password pass:$PASSWORD \
-in $PFX_FILE \
-nocerts \
-nodes \
-out $KEY_FILE
# ========== 步骤4:生成 CSR ==========
echo ">>> 生成证书签名请求..."
keytool -certreq \
-sigalg SHA256withRSA \
-storepass $PASSWORD \
-alias $CERT_ALIAS \
-keystore $JKS_FILE \
-file $CSR_FILE \
-ext san=$SAN_LIST
# ========== 步骤5:验证 CSR ==========
echo ">>> CSR 内容验证:"
openssl req -text -noout -verify -in $CSR_FILE
# ========== 步骤6:打包 ==========
echo ">>> 打包所有文件..."
zip ${DOMAIN_NAME}.zip $JKS_FILE $PFX_FILE $KEY_FILE $CSR_FILE
echo ""
echo "========================================"
echo " CSR 生成完成!"
echo "========================================"
echo "请将 ${CSR_FILE} 提交给证书管理员"
echo "私钥文件请妥善保管,不要泄露!"
3.5 生成的文件用途
3.6 收到证书后如何导入?
CA 签发后会返回:服务器证书、中间证书、根证书。需要按顺序导入:
# 方法1:导入到 JKS(Java 应用)
# 按顺序:根证书 → 中间证书 → 服务器证书
keytool -import -alias root -keystore server.jks -file root.crt -trustcacerts
keytool -import -alias intermediate -keystore server.jks -file intermediate.crt
keytool -import -alias server -keystore server.jks -file server.crt
# 方法2:创建 PEM 证书链(Nginx/Apache)
# 合并服务器证书和中间证书
cat server.crt intermediate.crt > fullchain.crt
# Nginx 配置
# ssl_certificate /path/to/fullchain.crt;
# ssl_certificate_key /path/to/server.key;
3.7 证书续期:企业证书如何更新
企业级证书通常有效期 1-2 年,到期前需要续期。续期流程与首次申请类似,但有一些注意事项:
续期时机
# 检查证书剩余有效期
openssl x509 -in server.crt -noout -dates
# 计算剩余天数
echo "证书将在 $(($(date -d "$(openssl x509 -in server.crt -noout -enddate | cut -d= -f2)" +%s) - $(date +%s))) 秒后过期"
# 建议:证书过期前 30 天开始续期流程
续期方式选择
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 复用私钥 | 使用原有私钥重新生成 CSR | 快速续期,无需重新部署密钥 |
| 新建密钥 | 生成新的密钥对和 CSR | 更安全,推荐做法 |
| 自动续期 | 部分 CA 提供自动续期服务 | 减少运维工作量 |
续期脚本示例
#!/bin/bash
# ============================================================
# 企业级证书续期脚本
# ============================================================
DOMAIN_NAME="example.com"
OLD_CERT="server.crt"
CSR_FILE="renew_${DOMAIN_NAME}.csr"
# 检查证书是否需要续期(30天内过期)
check_renewal() {
if openssl x509 -in $OLD_CERT -noout -checkend 2592000 2>/dev/null; then
echo "证书有效期充足,暂不需要续期"
exit 0
fi
echo "证书将在30天内过期,开始续期流程..."
}
# 方式1:复用现有私钥生成 CSR(快速续期)
renew_with_existing_key() {
# 从现有证书提取公钥信息
openssl x509 -in $OLD_CERT -noout -text | grep -A1 "Subject Alternative Name"
# 使用现有私钥生成新 CSR
openssl req -new \
-key server.key \
-out $CSR_FILE \
-subj "/C=CN/ST=Beijing/L=Beijing/O=YourCompany/OU=IT/CN=portal.example.com"
echo "CSR 已生成: $CSR_FILE"
echo "请提交给证书管理员"
}
# 方式2:生成新的密钥对(推荐)
renew_with_new_key() {
# 生成新私钥
openssl genrsa -out server_new.key 4096
# 生成新 CSR
openssl req -new \
-key server_new.key \
-out $CSR_FILE \
-subj "/C=CN/ST=Beijing/L=Beijing/O=YourCompany/OU=IT/CN=portal.example.com" \
-addext "subjectAltName=DNS:portal.example.com,DNS:api.example.com"
echo "新密钥和 CSR 已生成"
echo "私钥: server_new.key (请妥善保管)"
echo "CSR: $CSR_FILE (提交给证书管理员)"
}
# 执行续期检查
check_renewal
# 选择续期方式
echo "请选择续期方式:"
echo "1) 复用现有私钥(快速)"
echo "2) 生成新密钥对(更安全,推荐)"
read -p "请输入选项 [1/2]: " choice
case $choice in
1) renew_with_existing_key ;;
2) renew_with_new_key ;;
*) echo "无效选项"; exit 1 ;;
esac
续期后部署
# 收到新证书后,替换旧证书
cp server.crt server.crt.bak # 备份旧证书
cp new_server.crt server.crt
# 如果生成了新私钥,也要更新
cp server_new.key server.key
# 验证证书和私钥是否匹配
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
# 两个 MD5 值应该相同
# 重启服务
nginx -t && nginx -s reload
# 或
systemctl restart tomcat
四、两种方案对比总结
4.1 一图看懂差异
4.2 如何选择?
| 你的场景 | 推荐方案 | 原因 |
|---|---|---|
| 个人博客、作品集 | Let's Encrypt | 免费、自动、够用 |
| 小团队项目、测试环境 | Let's Encrypt | 快速部署、零成本 |
| 企业官网 | OV 证书 | 显示公司名,更专业 |
| 金融、支付系统 | EV 证书 | 最高信任级别 |
| 内网系统、企业PKI | CSR 模式 | 符合企业安全规范 |
| 需要通配符证书 | Let's Encrypt | 免费支持通配符 |
五、实用技巧与常见问题
5.1 证书安全最佳实践
# 1. 私钥权限:只有 root 可读
chmod 600 private.key
chown root:root private.key
# 2. 证书权限:所有人可读
chmod 644 server.crt
chown root:root server.crt
# 3. 检查证书有效期
openssl x509 -in server.crt -noout -dates
# 4. 验证证书链完整性
openssl verify -CAfile ca-bundle.crt server.crt
# 5. 查看证书详细信息
openssl x509 -in server.crt -text -noout
5.2 常见问题解答
Q1: 通配符证书为什么必须 DNS 验证?
因为通配符证书覆盖所有子域名,CA 需要验证你对整个域名的控制权。HTTP 验证只能证明你控制某个特定主机,无法证明对整个域名的所有权。
Q2: CSR 可以重复使用吗?
不建议。每次申请新证书时应生成新的 CSR 和新的私钥,这样更安全,也能避免密钥泄露风险。
Q3: 证书链是什么?为什么重要?
浏览器需要完整的信任链来验证证书。如果缺少中间证书,浏览器会报"证书不可信"错误。
Q4: JKS 和 PKCS#12 怎么互转?
# JKS → PKCS#12
keytool -importkeystore \
-srckeystore server.jks -srcstoretype JKS \
-destkeystore server.p12 -deststoretype PKCS12
# PKCS#12 → JKS
keytool -importkeystore \
-srckeystore server.p12 -srcstoretype PKCS12 \
-destkeystore server.jks -deststoretype JKS
Q5: 如何测试 HTTPS 配置?
# 测试 SSL 配置
openssl s_client -connect example.com:443 -servername example.com
# 在线测试工具
# https://www.ssllabs.com/ssltest/
六、总结
选择证书方案,就像选择出行方式:
- 🚴 Let's Encrypt = 骑共享单车,免费、方便、适合短途(个人项目)
- 🚗 OV 证书 = 开私家车,正式、体面、适合商务(企业官网)
- 🚀 EV 证书 = 坐头等舱,顶级配置、严格审核(金融电商)
对于大多数个人开发者和小团队,Let's Encrypt 提供的免费自动化方案已经完全够用。企业场景则根据合规要求和信任级别选择合适的证书类型。
记住:私钥是核心机密,证书是公开身份,CSR 是申请书。搞懂这三者的关系,证书管理就不再神秘了。
📜 版权声明
本文作者:王梓 | 原文链接:https://www.bthlt.com/note/369625131-Linux网站也要身份证:HTTPS 证书申请指南
出处:葫芦的运维日志 | 转载请注明出处并保留原文链接


📜 留言板
留言提交后需管理员审核通过才会显示