结论: 服务器上安装 SSL 证书的标准流程是四步:生成私钥与 CSR、向 CA 提交申请完成域名验证、下载签发好的证书文件、在 Web 服务器里配置证书与私钥路径并重载服务。绝大多数安装失败都不是流程错,而是证书链不完整、私钥与证书不匹配、中间证书缺失这三类问题。
HTTPS 早已不是"要不要做",而是"不做就出局"。截至 2026 年,主流浏览器对所有 HTTP 页面都会明确标记为"不安全",Chrome 与 Edge 甚至会对表单输入框给出额外警告;同时微信小程序、App Store 的 ATS 策略、以及各类支付回调接口都强制要求 HTTPS。
但"装证书"这一步对很多人来说依然是个黑盒:CA 给了好几个文件不知道用哪个,Nginx 配完还是提示证书不受信任,Tomcat 只认 Java Keystore 格式束手无策。本教程以 Nginx 1.26、Apache 2.4、Tomcat 10、IIS 10 四种主流 Web 服务器为基准,把完整流程和每个平台的差异讲透。
第一步:搞清楚你要装的是哪一种证书
SSL/TLS 证书按验证强度分为 DV、OV、EV 三档,区别不在于加密强度——三者都能达到 AES-256 级别加密,而在于 CA 对申请者身份的审核深度。 选错档不会让网站更安全,只会多花钱或达不到合规要求。
DV/OV/EV 证书对比表
| 对比项 | DV(域名验证) | OV(组织验证) | EV(扩展验证) |
|---|---|---|---|
| 验证内容 | 仅验证域名控制权 | 域名 + 企业营业执照等组织真实性 | 域名 + 严格的组织/法律/物理存在核查 |
| 签发时间 | 几分钟 ~ 1 小时 | 1 ~ 5 个工作日 | 1 ~ 7 个工作日 |
| 浏览器表现 | 地址栏锁标 | 地址栏锁标 + 证书详情显示公司名 | 锁标 + 证书详情显示公司名(新版浏览器已取消绿色地址栏) |
| 适用场景 | 个人站、博客、测试环境、API 接口 | 企业官网、中小企业业务系统 | 金融、支付、电商、政府采购等强信任场景 |
| 参考价格(截至 2026 年 1 月) | 免费 ~ 数百元/年 | 数千元/年 | 数千至上万元/年,以官网实时报价为准 |
| 支持通配符 | 支持 | 支持 | 支持(部分 CA 限制) |
必须澄清两个流传很广的误解:
- 误解一:EV 证书能提升 SEO 排名。 不能。搜索引擎官方从未把证书类型作为排名加权因子,HTTPS 本身才是(且权重极小)。
- 误解二:EV 更安全。 加密强度与 DV 完全一致。EV 的价值在于"身份可被人工核验",适合需要向客户证明"这个网站确实属于某公司"的场景。自 Chrome 77 起,EV 的绿色地址栏已被移除,只能在证书详情里看到组织名。
域名覆盖范围的三种形式
| 类型 | 覆盖范围 | 示例 | 说明 |
|---|---|---|---|
| 单域名(Single Domain) | 一个完全限定域名 | www.example.com | 注意很多 CA 的默认免费单域名证书不含裸域名,需两者都在 SAN 里 |
| 多域名 SAN/UCC | 最多数百个不相关域名 | example.com、demo.cn、a.net | 一张证书打包多个域名,便于统一管理 |
| 通配符 Wildcard | 一级通配 *.example.com | 匹配 blog、shop 等任意一级子域名 | 不匹配裸域名 example.com,也不匹配 a.b.example.com 二级子域名 |
**重要提醒:通配符证书 *.example.com 不包含 example.com。** 需要两者都覆盖时,申请时必须同时填写两个 SAN 条目:*.example.com 和 example.com。这是证书不匹配报错的常见来源之一。
第二步:生成私钥与 CSR
CSR(Certificate Signing Request,证书签名请求)里只有公钥和申请信息,私钥永远留在你的服务器上,绝对不要发给 CA。 这步做错会导致证书无法使用且必须重签。
# 创建证书目录并限制权限
sudo mkdir -p /etc/ssl/private /etc/ssl/certs
sudo chmod 700 /etc/ssl/private
# 方式一:一条命令同时生成 2048 位私钥与 CSR(推荐 RSA 2048 或 ECDSA P-256)
openssl req -new -newkey rsa:2048 -nodes \
-keyout /etc/ssl/private/example.com.key \
-out /etc/ssl/certs/example.com.csr \
-subj "/C=CN/ST=Guangdong/L=Shenzhen/O=Example Tech Co., Ltd./OU=IT Dept/CN=example.com"
# 方式二:已有私钥,用配置文件追加 SAN 后再生成 CSR(多域名/通配符必用)
cat > /tmp/openssl.cnf <<'EOF'
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = CN
ST = Guangdong
L = Shenzhen
O = Example Tech Co., Ltd.
CN = example.com
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = *.example.com
EOF
openssl req -new -sha256 \
-key /etc/ssl/private/example.com.key \
-out /etc/ssl/certs/example.com.csr \
-config /tmp/openssl.cnfCSR 里几个字段的含义与填写规范:
C(Country):两位国家代码,中国填CN。ST(State/Province)、L(Locality):省份与城市,用英文填写。O(Organization):OV/EV 证书必须与营业执照上的企业全称完全一致,否则会被 CA 驳回。CN(Common Name):主域名。自 2018 年起浏览器已不再看 CN,全部以 SAN 为准,但 CA 仍要求填写。subjectAltName:现代浏览器唯一的域名匹配依据,所有要覆盖的域名必须写在这里。
生成后务必自检再提交,避免来回收发的时间成本:
# 查看 CSR 内容,重点确认 CN 与 SAN
openssl req -in /etc/ssl/certs/example.com.csr -noout -text | grep -A2 "Subject Alternative Name"
openssl req -in /etc/ssl/certs/example.com.csr -noout -subject
# 校验私钥格式与强度
openssl rsa -in /etc/ssl/private/example.com.key -check -noout第三步:Nginx 安装 SSL 证书
Nginx 需要两个文件:证书文件(含自己 + 中间证书的完整链)和私钥;ssl_certificate 必须指向完整的 fullchain,否则部分客户端报不受信任。 这是 Nginx 上排名第一的配置错误。
CA 提供的文件通常有三个:example.com.crt(域名证书)、ca_bundle.crt(中间/根证书链)、example.com.key(你自己的私钥)。按下面方式合并:
# 合并顺序必须是:域名证书在前,中间证书在后
cat example.com.crt ca_bundle.crt > /etc/ssl/certs/example.com_fullchain.crt
# 校验私钥与证书的公钥是否匹配(三条命令输出必须完全一致)
openssl x509 -noout -modulus -in /etc/ssl/certs/example.com_fullchain.crt | openssl md5
openssl rsa -noout -modulus -in /etc/ssl/private/example.com.key | openssl md5
openssl req -noout -modulus -in /etc/ssl/certs/example.com.csr | openssl md5
# 校验整条证书链是否完整
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/example.com_fullchain.crt
# 期望输出:example.com_fullchain.crt: OK完整的 Nginx HTTPS 站点配置,包含强制跳转、HTTP/2、HSTS 与安全加固:
# HTTP 全部 301 跳 HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on; # Nginx 1.25.1+ 用此写法;旧版本写 listen 443 ssl http2
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/example.com_fullchain.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# 仅 TLS 1.2/1.3,禁用已废弃协议
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# 会话复用:降低握手开销
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling:把证书状态查询结果随握手返回,加快验证
ssl_stapling on;
ssl_stapling_verify on;
resolver 223.5.5.5 8.8.8.8 valid=300s;
resolver_timeout 5s;
# HSTS:告诉浏览器半年内只用 HTTPS 访问(上线稳定后再开,回退成本高)
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}配置完成后:
sudo nginx -t && sudo systemctl reload nginx
# 在线验证握手与链完整性(看 Verify return code 是否为 0)
openssl s_client -connect example.com:443 -servername example.com /dev/null | openssl x509 -noout -dates -subject -issuer
# 用 SSL Labs 在线评分(目标 A 及以上)
# https://www.ssllabs.com/ssltest/analyze.html?d=example.com第四步:Apache / Tomcat / IIS 三个平台的安装要点
三个平台的共同点是都需要"私钥 + 完整证书链",差异只在于文件格式和加载方式。 Apache 用 PEM 明文即可,Tomcat 需要 Java Keystore(JKS 或 PKCS12),IIS 需要 Windows 的 PFX 容器格式。
Apache 2.4
Apache 需要三个独立文件路径,且必须先启用 mod_ssl:
sudo a2enmod ssl ssl_session_cache headers
sudo systemctl restart apache2
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/ca_bundle.crt
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder off
SSLSessionTickets off
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
注意:Apache 2.4.8 起 SSLCertificateChainFile 已废弃,可把中间证书直接追加到 SSLCertificateFile 指向的文件末尾。老版本必须保留该指令。
Tomcat 10
Tomcat 只认 Keystore,需要先用 OpenSSL 合成 PKCS12 再用 keytool 转成 JKS:
# 1) 合成 PKCS12(-name 指定别名,下一步要用)
openssl pkcs12 -export \
-inkey /etc/ssl/private/example.com.key \
-in /etc/ssl/certs/example.com.crt \
-certfile /etc/ssl/certs/ca_bundle.crt \
-name tomcat \
-out /etc/ssl/private/example.com.p12
# 会提示设置导出密码,务必记录
# 2) 转成 Java Keystore(Tomcat 10 推荐直接使用 PKCS12,无需转 JKS)
keytool -importkeystore \
-srckeystore /etc/ssl/private/example.com.p12 -srcstoretype PKCS12 \
-destkeystore /etc/ssl/private/example.com.jks -deststoretype JKS \
-srcalias tomcat -destalias tomcat然后修改 $CATALINA_HOME/conf/server.xml:
重启 Tomcat 后检查 catalina.out 有无 Alias name [tomcat] 的输出,那表示私钥已成功加载。JDK 17 及以上建议直接用 keystoreType="PKCS12",可以跳过 JKS 转换这一步。
IIS 10(Windows Server 2022)
IIS 需要在 Windows 证书存储里导入 PFX,再绑定到站点。PowerShell 方式:
# 1) 先在 OpenSSL 侧生成 PFX(也可在 Linux 上生成后传到 Windows)
# openssl pkcs12 -export -out example.com.pfx -inkey example.com.key -in example.com.crt -certfile ca_bundle.crt
# 2) 以管理员权限 PowerShell 导入到本地计算机证书存储的 "My" 容器
$pwd = ConvertTo-SecureString -String "你的导出密码" -Force -AsPlainText
Import-PfxCertificate -FilePath C:\cert\example.com.pfx `
-CertStoreLocation Cert:\LocalMachine\My -Password $pwd -Exportable
# 3) 绑定到 IIS 站点(WebAdministration 模块)
Import-Module WebAdministration
$binding = Get-WebBinding -Name "Default Web Site" -Protocol "https"
if (-not $binding) {
New-WebBinding -Name "Default Web Site" -Protocol "https" -Port 443 -SslFlags 1
}
$binding = Get-WebBinding -Name "Default Web Site" -Protocol "https"
$binding.AddSslCertificate("证书指纹Thumbprint", "my")
# 4) 禁用老旧协议(写入注册表后需重启)
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" -Force
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" -Name "Enabled" -Value 0证书指纹(Thumbprint)可以在"证书管理器 > 本地计算机 > 个人 > 证书"里双击证书查看,或在 PowerShell 中用 Get-ChildItem Cert:\LocalMachine\My 获取。IIS 上证书链缺失通常表现为"Windows 能正常访问,安卓/iOS 报不受信任",基本都是中间证书没安装到 Cert:\LocalMachine\Intermediate 导致的。
第五步:证书链完整性、到期巡检与自动续期
证书链不完整是 HTTPS 故障的头号原因,占实际排错案例的一半以上。 它的诡异之处在于:桌面 Chrome 会因为 AIA 追补特性自动下载缺失的中间证书从而显示正常,但 curl、Java、Android WebView 不会,于是"我电脑上是好的"成了最误导人的证据。
排错与验证的黄金三条命令:
# 1) 查看服务端实际下发了几张证书。返回 1 张说明缺中间证书
openssl s_client -connect example.com:443 -servername example.com -showcerts /dev/null | grep -c "BEGIN CERTIFICATE"
# 2) 检查主题(subject)与颁发者(issuer)能否首尾相接
openssl s_client -connect example.com:443 -servername example.com /dev/null | openssl x509 -noout -subject -issuer
# 3) 验证握手状态(Verify return code: 0 (ok) 才算通过)
openssl s_client -connect example.com:443 -servername example.com /dev/null | grep "Verify return code"到期巡检建议做成定时任务,而不是靠人记着。下面是一个可放进 crontab 的轻量脚本:
#!/usr/bin/env bash
# /opt/scripts/check-cert-expiry.sh —— 每天检查证书剩余天数,低于阈值发告警
DAYS_LEFT=$(echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null \
| awk -F'=' '{cmd="date -d \""$2"\" +%s"; cmd | getline d; close(cmd); print int((d-'"$(date +%s)"')/86400)}')
THRESHOLD=15
if [ "${DAYS_LEFT:-999}" -lt "$THRESHOLD" ]; then
echo "ALERT: example.com 证书剩余 ${DAYS_LEFT} 天" | mail -s "SSL 证书即将到期" ops@example.com
fi# 加入 crontab,每天上午 9 点检查
0 9 * * * /opt/scripts/check-cert-expiry.sh >> /var/log/cert-check.log 2>&1自动续期如果使用 Let's Encrypt(免费 DV 证书,有效期 90 天),certbot 是标准方案。截至 2026 年,certbot 官方推荐使用 snap 安装以获得最新版本:
# 安装 certbot(Nginx 插件 + DNS 插件按需)
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
# HTTP-01 方式签发(需要 80 端口对外可达)
sudo certbot certonly --nginx -d example.com -d www.example.com
# 通配符证书必须用 DNS-01 方式
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.example.com" -d example.com
# 测试续期(--dry-run 不会真的消耗签发配额)
sudo certbot renew --dry-run
# systemd timer 每 12 小时自动检查续期,并重载 Nginx
sudo systemctl enable --now snap.certbot.renew.timer
sudo certbot renew --deploy-hook "systemctl reload nginx"Let's Encrypt 有几个硬性配额上限,规划时务必注意:同一注册域名每周 50 张证书、每域名每周 5 张重复证书、每小时 5 次失败验证。调 --dry-run 不会计入配额,但误用它做压力测试会触发限流。
常见误区 / 排错提示
- 误区一:把私钥文件用 .crt 拷给同事。 私钥泄露等于证书可被伪造,必须重新签发(Revoke + Reissue)。
/etc/ssl/private目录权限应是 700,私钥文件 600。 - 误区二:
ssl_certificate只配了域名证书没配中间证书。 桌面浏览器正常、部分客户端报错,就是这个原因。永远用 fullchain。 - 误区三:证书生效后仍然重启 Nginx 而不是 reload。
reload才能不中断存量连接地加载新证书;若执行nginx -s reload后证书仍没变,检查是否有旧 worker 进程未退出。 - 误区四:一台服务器多个 HTTPS 站点只配了一个 default_server 的证书。 没配证书且被 SNI 命中的 server 块会回退到默认 SSL 站点,返回错误证书。每个 server 块都应该有独立的
ssl_certificate。 - 误区五:Tomcat 里 keyAlias 与导出时
-name不一致。 表现是启动日志报Alias name [xxx] does not identify a key entry。用keytool -list -v -keystore xxx.jks确认别名。 - 误区六:改了证书后浏览器还报旧证书。 是本地 SSL 会话缓存或 OCSP 缓存没清。用隐身窗口或
openssl s_client绕过浏览器验证,不要反复重装。
常见问题(FAQ)
SSL 证书安装后浏览器还是提示不安全,是什么原因?
最常见的原因是证书链不完整或页面存在混合内容(Mixed Content)。 先用 openssl s_client -connect 域名:443 -servername 域名 检查握手是否正常、链是否返回 2~3 张证书;如果是锁标但显示"部分内容不安全",则是页面里有 http:// 的 js/css/图片资源,需要在 Nginx 加 add_header Content-Security-Policy "upgrade-insecure-requests"; 或把资源改成相对协议。
免费 SSL 证书和付费证书有什么区别?
加密强度完全相同,差别在于有效期、验证等级、保险赔付与技术支持。 免费证书以 Let's Encrypt 为代表,DV 级、90 天有效期、需自动续期、无赔付;付费 OV/EV 提供企业身份核验、最长 13 个月有效期(截至 2026 年 CA/B 论坛规定)、数十万至数百万美元赔付和技术支持。企业对外业务建议 OV 起,内部系统与个人站用免费证书完全够。
一张证书可以在多台服务器上用吗?
可以,只要多个节点对外提供的是同一个域名。 把私钥与证书文件同步到所有节点即可,这对负载均衡集群是标准做法。需要注意两点:一是私钥分发要走加密通道(如 rsync over SSH、Vault),二是不要在宝塔之类的面板里重复申请同一域名的新证书,容易触发 CA 的重复证书配额限制。
通配符证书能把根域名也保护了吗?
**默认情况下不能,必须在 SAN 里显式同时列出 *.example.com 和 example.com。** 原因是通配符只在证书的 subjectAltName 里声明了 .example.com 这一个条目,而浏览器自 2018 年起完全按 SAN 匹配域名,裸域名不在列表里就会被判为证书不匹配。另外通配符只匹配一级子域名,a.b.example.com 这种二级子域名不会被 .example.com 覆盖,需要单独添加 SAN 条目或再申请一张 *.b.example.com 证书。申请时的判断方法很简单:把所有要保护的域名逐条写进 SAN,签发后用 openssl x509 -noout -text | grep -A2 "Subject Alternative Name" 核对一遍再部署。
证书到期没续会怎样?怎么防止忘记?
到期后所有访问该站点的浏览器会弹出红色警告页,用户需手动点击"继续"才能访问,实际等同于业务中断。 防御手段有三层:一是 certbot + systemd timer 自动续期;二是部署上述巡检脚本并在剩余 15 天时告警;三是购买支持的平台可用 SSL 证书,把证书基本信息(含到期时间)登记到台账或 CMDB 中统一管理。
用 CDN 时证书该装在哪一层?
两处都要装:CDN 上装面向用户的证书(回调必须是 https),源站也要装证书(可以是自签名或 CDN 厂商提供的源站证书)。 如果 CDN 与源站之间配置了严格校验,则源站必须用有效公开信任的证书,否则回源握手失败返回 5xx。用 CDN 厂商的一键托管证书(如腾讯云 SSL、阿里云证书中心托管)可以避免手动轮换。
企业QQ咨询




