上一篇【001】把 HTTP 这一条「明文应用层」捋了一遍。一旦站点改成 HTTPS ,同样还是 HTTP 语义(方法、状态码、Header、JSON),但 TCP 连接建立之后、HTTP 报文发送之前 ,多了一层 TLS(前身常叫 SSL) 协商:协商出对称密钥、校验服务器身份、(可选)校验客户端。联调时常见的「证书过期」「域名和证书不一致」「小程序要求合法 HTTPS」「Java 调合作伙伴接口 PKIX 报错」大半都落在这层上。
这篇用「能排障、能跟运维对齐、能配 Spring Boot / 反代 / 本地证书」为度做一次加量粗解 ,仍然不替密码学教材。下面我按「HTTPS 解决啥 → 证书与链 → TLS 版本与握手直觉 → Spring Boot 实操 → 反代与转发头 → Java 当客户端 → 命令行排障 → 自签与 SAN → 双向认证与小场景 → 小程序合法域名」往下聊;每个大节里都尽量塞可复制的配置与命令。
1. HTTPS 在解决什么问题 ✉
在 HTTP 上,链路中的设备若能看到你的流量,就能读到 URL(含敏感 query)、Header、Body(含 token------敏感凭证更应放 Header 而非 query)。HTTPS = HTTP over TLS,TLS 主要负责三件事(和「机密性 / 完整性 / 身份」对应):
- 机密性:应用数据用协商出的对称密钥加密,窃听者拿到的是密文。
- 完整性 :现代套件多用 AEAD,篡改更容易被对端拒收或校验失败。
- 身份(对服务端而言最显眼) :服务端用 X.509 证书绑定域名(及公钥),客户端验证链与主机名后,才相信「当前连接对端是该域名背后的服务」。
还要知道两个「周边」问题:
混合内容(Mixed Content)
页面是 HTTPS,但页面里的脚本、接口、图片还用 http:// 去拉,浏览器可能拦截 或降级处理,表现为「线上环境只有部分资源失败」。前后端联调时,统一入口协议很关键。
HSTS(HTTP Strict Transport Security)
服务端通过响应头要求浏览器只走 HTTPS 访问该域一段时间,可减少「首次仍打到 HTTP」被劫持的风险。配在云/WAF/Nginx/Spring 上都有可能;开发本地一般碰不到,上线要听安全/运维规范。
和 Java 后端的关系 :你在内嵌 Tomcat 上开 server.ssl.*,或前面用 Nginx/Ingress 终结 TLS 再回源 HTTP,都要理解证书与域名;Java 作为 HTTPS 客户端 (RestTemplate、RestClient、Feign、SDK)时还会单独碰到 truststore 与协议/套件不匹配问题。
2. 证书与证书链里有什么 📜
网站给你的材料一般是 X.509 。常见存放形态:
| 形态 | 说明 |
|---|---|
| PEM | Base64 + -----BEGIN CERTIFICATE----- 头尾,可读文本,可链式拼接多个证书。 |
| DER | 二进制,扩展名不一定是 .der,有时 .crt 既是 PEM 又是 DER,需用 openssl x509 -in file -text -noout 试读。 |
| PKCS#12(.p12 / .pfx) | 一个文件里常含私钥 + 证书链 (+ 密码保护),Java keytool、Spring key-store-type: PKCS12 都爱用它。 |
2.1 字段里你最该盯的
| 概念 | 你需要知道的 |
|---|---|
| SAN(Subject Alternative Name) | 现代浏览器校验主名 看 SAN;仅 CN(Common Name) 不含 SAN 的老证书在部分环境会踩坑。你的访问域名/泛域名应出现在 SAN 列表里。 |
| Issuer | 颁发者:公共 CA、企业私有 CA、或自签名(Issuer = Subject)。 |
| 有效期 | notBefore ~ notAfter。过期必挂;建议设到期告警(提前 30 天很常见)。 |
| 公钥与用途 | 与服务器私钥 成对;私钥绝不能进代码仓库。 |
| 证书链顺序 | 典型:站点证书 → 中间证书(可多层)→ 根证常已在客户端信任库。服务端配置时要避免「只发了站点证、没发中间证」。 |
2.2 DV / OV / EV(面试与采购常听)
- DV:验证域名控制权,签发快,浏览器地址栏一般只显示锁。
- OV / EV :多组织信息与更严审核,不能当作「绝对安全」,业务安全仍靠你自己(鉴权、防重放、日志等)。
2.3 公网 vs 内网
- 公网:Let's Encrypt、DigiCert 等签的链,手机/浏览器/小程序默认可信。
- 内网/自签 :客户端不信任 →
PKIX path building failed。正规做法是把企业根 CA 导入 各环境的 truststore,或统一用私有 ACME/PKI;开发机临时导入要有限度。
吊销(CRL / OCSP)
浏览器与部分客户端会检查证书是否被吊销;排障时若遇「极少数客户端不行」,除链以外也可让运维侧看一眼吊销可达性(企业环境才多见)。
3. TLS 版本、套件与握手直觉 🔐
3.1 TLS 1.2 和 1.3 的差异(工程师版)
| 项 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 典型往返(RTT) | 完整握手常见 2-RTT(外加 TCP) | 1-RTT 完整握手更常见 |
| 套件 | 历史上套件繁杂,配置错误易出现弱套件 | 废弃大量旧套件,缺省更安全 |
| 中间人可见度 | 设计年代早,需更注意禁用旧协议 | 行业整体在推 1.3 |
实践 :生产侧听运维/WAF 统一策略;Java 侧若指定过「只允许 TLSv1.2」之类 JVM 参数,升级时要和网关策略对齐,避免 protocol_version / handshake_failure。
3.2 握手「剧情」仍是这几步(与 1.2 对齐理解)
- ClientHello :协议版本上限、随机数、支持的套件、SNI (你访问的域名)、扩展(ALPN 里可协商
h2/http/1.1等)。 - ServerHello + Certificate :服务端选定参数,下发证书链。
- 客户端验链、验主机名(证书是否覆盖 SNI 里的名字)。
- 密钥交换 (ECDHE 等)→ 双方得到会话密钥。
- Finished 后,应用数据(即 HTTP)才加密传输------【001】里的报文在这之后才出现。
你要记的结论 :业务 HTTP 报错与 TLS 报错层级不同 ;curl/浏览器若在握手阶段失败,根本不会 到你的 @GetMapping。
3.3 SNI(Server Name Indication)为何重要
同一台机、同一个公网 IP 上可能挂成千上万个 HTTPS 虚拟主机,靠的就是 TLS 握手 ClientHello 里带的 SNI 。老旧的 Java 8 早期 或未正确配置 SNI 的客户端,访问多域名 HTTPS 时可能莫名其妙失败;你现在主力 JDK 17 一般问题不大,但排障时心里要有这根弦。
3.4 会话恢复(了解即可)
Session ID / Session Ticket 让同客户端重复建连时少算密钥,体感主要是「复访更快」。深度排障很少从零扣这个,但若 CDN 文档让你开/关 ticket,知道它和「会话复用」有关即可。
4. Spring Boot 3.x 里开 HTTPS(内嵌容器)☕
很多团队 不在 JVM 上终结 TLS,但若你需要「单机直出 HTTPS」或本地对齐生产,可以用下面几类配置。
4.1 PKCS#12(.p12 / .pfx)------最常见
yaml
server:
port: 8443
ssl:
enabled: true
bundle: classpath:keystore.p12
key-store-password: ${SSL_KEYSTORE_PASSWORD}
key-store-type: PKCS12
key-alias: myalias
不同 Boot 小版本里 key-store 与 bundle 的键名请以你当前 3.3.x 官方文档 为准(有的示例仍写 server.ssl.key-store)。要点不变:
- key-store-password :库口令;key-password 若与库口令不同需单独指定。
- key-alias:一个 p12 里多个别名时必填对。
- 生产口令走环境变量 / Secret,勿提交 Git。
HTTP 与 HTTPS 同时开 :可以用 两套端口 (例如 8080 HTTP + 8443 HTTPS),或只做反代层双协议;若只要「强制跳 HTTPS」,多在 网关/Nginx 做 301,比在业务里写过滤器更常见。
4.2 PEM(证书文件 + 私钥文件)
yaml
server:
port: 8443
ssl:
certificate: classpath:cert.pem
certificate-private-key: classpath:key.pem
注意:私钥文件权限 在 Linux 上应收紧(仅运行用户可读)。链若分多段,按文档要求拼成服务端认可的 fullchain 形态。
4.3 协议与套件(进阶兜底)
若安全基线要求「仅 TLSv1.2+」或指定套件,常见是通过 内嵌容器定制 或 反向代理统一策略 。Boot 层若暴露 server.ssl.enabled-protocols / ciphers(以文档为准),改前务必和运维对齐,避免老式客户端全挂。
4.4 Actuator 与健康检查
Kubernetes 探针常打 HTTP。若你整站只开在 HTTPS,要么:
- 探针走 独立 management 端口(仅内网),仍 HTTP;要么
- 探针路径在明文侧单独暴露(由平台规范约束)。
不要想当然把「业务 URL 必须 https」让探针也跟着复杂化,除非平台明确要求。
4.5 信任「反代传来的 https」------Forwarded 头
见下一节与 5.3 联动:X-Forwarded-Proto: https、X-Forwarded-Host 等会影响 Spring MVC 的绝对 URL 生成 、Cookie 的 Secure 、重定向 Location。Boot 3 常用:
yaml
server:
forward-headers-strategy: framework
或 native------具体取值请对照 当前 minor 文档与你们网关实际发的头。没配时 ,常见 bug 是:登录后重定向成 http:// 导致无限跳或 Cookie 丢失。
5. 反向代理终结 TLS(更常见的生产形态)📎
5.1 典型拓扑
text
浏览器 --HTTPS--> 云 LB / Nginx / Ingress --HTTP--> Spring Boot :8080
\--HTTPS mTLS--> (少数场景)
TLS 在「边缘」终结,内网回源 可走明文 HTTP(配合安全组/专线策略)。你的 Java 日志里 RemoteAddr 往往是反代 IP,真实客户端在 X-Forwarded-For 里(注意伪造链,信任边界以网关抹写为准)。
5.2 Nginx 配置加深一版
nginx
upstream spring_app {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 443 ssl;
http2 on;
server_name api.example.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
# 按公司基线补 ssl_protocols / ssl_ciphers 等
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://spring_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
fullchain.pem:站点 + 中间证书;别只拷「叶子证」。
WebSocket :若路径走 WS,要额外 Upgrade、Connection 相关头,或使用 Nginx/网关的 websocket 专用示例。
5.3 Spring 侧为何要认 Forwarded
场景:用户访问的是 https://api.example.com,网关回源 http://127.0.0.1:8080。Spring 若不知道「外面是 https」,生成的 redirect 可能写成 http://,OAuth2 回调 、表单 action 、HATEOAS 等都会歪。配好 forward-headers-strategy 并只信任你家网关 IP 写的头(防 Spoof),是生产必备意识。
5.4 云厂商四层/七层 LB
七层 LB 往往在控制台上传证书,回源可指定 HTTP;注意 健康检查路径 、会话保持 与 TLS 只在入口 的组合。细节跟阿里云/腾讯云/AWS 控制台走,此处只强调:证书续期在 LB/CDN 控制台也可能发生,别忘了不仅 Nginx。
6. Java 作为客户端访问 HTTPS 上游 🎯
6.1 默认信任从哪来
JRE/JDK 带着 lib/security/cacerts (密码默认 changeit),里面是公共 CA 根。公网 HTTPS 一般够用。
6.2 keytool:看库、导入根证(示例)
bash
# 列出 cacerts 里别名(路径随 JDK 安装变)
keytool -list -keystore "%JAVA_HOME%\lib\security\cacerts" -storepass changeit
企业根证书导入(示例,别名自定):
bash
keytool -importcert -noprompt -alias corp-root -file corp-root.pem -keystore "%JAVA_HOME%\lib\security\cacerts" -storepass changeit
注意 :改系统 cacerts 影响整台机所有 Java 进程,很多公司改为 启动时挂自定义 truststore,或容器镜像层统一管理。
自定义 truststore 启动:
text
-Djavax.net.ssl.trustStore=E:/dev/corp-truststore.p12
-Djavax.net.ssl.trustStorePassword=yourSecret
-Djavax.net.ssl.trustStoreType=PKCS12
6.3 典型异常与含义
| 异常 / 日志关键字 | 更可能原因 |
|---|---|
PKIX path building failed |
不信任颁发链、缺根/中间、或连错环境(测网证书打生产域名) |
CertificateExpiredException |
证书过期 |
CertificateNotYetValidException |
本机时间不对或证书未生效 |
No subject alternative DNS name matching |
访问的 Host 不在证书 SAN |
javax.net.ssl.SSLHandshakeException |
协议/套件/证书错误的大箩筐,需打开 -Djavax.net.debug=ssl:handshake(仅排障短暂开) |
SunCertPathBuilderException |
常与 PKIX 同类,链构造失败 |
6.4 框架层:RestTemplate / RestClient / Feign
- 公网 CA:一般零配置。
- 私有 CA:运维发根证 → 进 truststore(推荐)→ 再谈代码。
- 「开发环境跳过校验」类
TrustManager:不要复制进生产;代码评审应拦。
Feign / HttpClient 若单独配了 SSL 上下文,要确认没有覆盖默认的 SNI 行为(少数老配置会踩坑)。
7. 联调与排障:命令、流程与表 ✅
7.1 curl
看握手与证书 (Windows 可把管道后换成 findstr):
bash
curl -v "https://api.example.com/actuator/health" 2>&1 | findstr /i "subject issuer expire SSL certificate"
指定解析(排除 DNS 捣乱):
bash
curl -v --resolve api.example.com:443:203.0.113.10 "https://api.example.com/"
7.2 openssl s_client(有 OpenSSL 的环境)
bash
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null
关注:证书链有几张 、Verify return code 是否 0、subject=CN / SAN、OCSP 相关输出(视版本)。
7.3 浏览器
Chrome:锁图标 → 连接是安全的 → 证书有效 ,看颁发者、有效期、使用者可选名称。
Safari / Firefox 路径略不同,原则一样:链、日期、域名。
7.4 排障流程(可当 check list)
- 先分清 :是握手失败 还是 HTTP 4xx/5xx(握手失败时很多监控探不到业务指标)。
curl -v/openssl s_client在出问题的同一网络环境跑(公司出口、用户家宽、机房内网)。- 核对 访问的 Host 与证书 SAN ;核对 系统时间。
- 服务器/Nginx 侧:
fullchain是否真 full;是否改过中间证未重启。 - Java 客户端:truststore 是否包含企业根;JVM TLS 版本是否过严或过旧。
- 仅部分移动网络 失败:想到 IPv6 、SNI、过时安卓 WebView、中间设备劫持等(需要抓包与运营侧信息)。
7.5 浏览器错误与可能原因(扩表)
| 现象 | 可能原因 |
|---|---|
NET::ERR_CERT_DATE_INVALID |
过期/未生效/本机时间错误 |
NET::ERR_CERT_COMMON_NAME_INVALID |
域名与 SAN 不匹配 |
ERR_CERT_AUTHORITY_INVALID |
自签或私有 CA 未被信任 |
NET::ERR_SSL_VERSION_OR_CIPHER_MISMATCH |
协议/套件过新或过旧 |
| 小程序合法域名失败 | 非 443 默认、TLS 不合规、证书链问题、域名未登记、业务未备案(政策以平台文档为准) |
8. 综合示例:本地证书与 Spring Boot 💻
8.1 最简自签(仅本机,带 SAN 更好)
/etc/hosts 或 Windows hosts 把 local.test 指到 127.0.0.1,用 SAN 覆盖该名字(OpenSSL 命令各版本用 req v3_req + subjectAltName 配置块;此处给思路,命令以你本机 OpenSSL 手册为准):
- 生成 私钥 + CSR + 自签 ,SAN 含
DNS:local.test、DNS:localhost。 - Spring:
server.ssl.certificate/certificate-private-key指向生成文件,server.port=8443。 - 浏览器首次仍会红屏 ------导入自签为受信任根 或每次点高级继续,团队规范通常禁止把这种证书用于联调小程序。
8.2 开发利器 mkcert(可选)
mkcert 在开发机上生成本地受信 CA,浏览器少红屏;仍非公网方案,上线与小程序无关。
8.3 「与生产一致」的路径
尽量用测试环境 已申请的正式域+正式证书(或 staging),连接到类生产网关,减少「本地自签一切正常、上云全挂」的落差。
9. 双向 TLS(mTLS)------知道边界即可 🔗
部分 开放银行 / 企业 B2B 要求 客户端也交证书 ,服务端校验「你是谁」。此时除服务端 server.ssl.*(trust-store 配合作方根或伙伴客户端认证配置)外,客户端 要配 keyStore (自己的证书+私钥)。细节强烈依赖对方接口文档与你们网关是否 offload,这里只提醒:遇到「要交客户端证书」的需求,别在业务代码里硬编码私钥路径密码,交给配置中心与密钥托管。
10. 小程序 / 开放平台的「合法域名」------和 HTTPS 的关系 📱
不同平台细则会变,开发时可按下面自查(以微信等官方文档为准,这里列工程常识):
- 接口域名必须是 HTTPS (小程序里
request合法域名列表)。 - 证书链完整、TLS 版本与套件满足平台最低要求(旧版文档常写不支持 SSLv3 等,需读当期说明)。
- 域名 已加到控制台「合法域名」,且与证书 SAN 一致。
- 部分能力要求 ICP 备案 、业务域名校验文件等------与纯 TLS 不同,但排障时一起查。
「后端同事说接口OK,小程序不通」------先手机浏览器 打开同一 URL 看证书;再用开发者工具 Network ;最后核对控制后台域名配置。
11. OpenSSL:带 SAN 的自签与 CSR 思路(可复制骨架)🧰
下面是一段「思路骨架 」:用独立配置文件把 SAN 写清楚,避免证书只有 CN=localhost、没有 SAN,被 Chrome 等直接标红。具体命令以你机器上 OpenSSL 3.x / 1.1.1 文档为准,路径自行替换。
第一步:写 openssl-san.cnf(示例)
ini
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[ dn ]
CN = local.test
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = local.test
DNS.2 = localhost
IP.1 = 127.0.0.1
第二步:生成私钥 + CSR + 自签证书(示例命令序列)
bash
openssl req -new -x509 -nodes -days 365 -keyout local.test.key -out local.test.crt -config openssl-san.cnf -extensions v3_req
生成的 local.test.crt + local.test.key 可交给 Spring Boot server.ssl.certificate / certificate-private-key(或先拼成 p12 再用 key-store)。记得 在 hosts 里把 local.test 指到本机,否则浏览器用别的名字访问仍会报域名不匹配。
验证书内容(看 SAN 是否在):
bash
openssl x509 -in local.test.crt -noout -text | findstr /i "Subject Alternative Name DNS"
Linux / macOS 把 findstr 换成 grep -A1 'Subject Alternative Name' 即可。
12. Let's Encrypt / 自动化续期(工程侧常识)📅
公网免费证书里 ACME(如 Let's Encrypt)最普及。工程上你要记住:
- 有效期短 (常见 90 天),必须 自动续期(certbot、caddy、云厂商托管证书等),不能靠人肉日历。
- 验证域名所有权常见 HTTP-01 (临时文件或路由)、DNS-01 (改 TXT 记录)。在 K8s/多副本 上要用平台认可的 controller,避免验证打到错误 Pod。
- 证书更新后,Nginx 要 reload 、部分 Java 进程要 热加载或滚动发布------别把「续期成功」当成「应用已用上新证」。
- 完整链 :ACME 客户端一般会给你
fullchain.pem,部署时用它,而不是只拿单张cert.pem。
你只写 Java 时,续期多在运维;但事故复盘里「昨晚续期、今早握手失败」要能参与对话。
13. Nginx 上再多了几招(安全 баз线 + mTLS 提示)🛡
13.1 安全基线(示意,具体以你们等保/基线为准)
nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# 若仍要 TLSv1.2,可配 ssl_ciphers ... 由安全组给清单;TLSv1.3 下多由 OpenSSL 默认择优
OCSP Stapling (减少客户端延迟、隐私略好)在 Nginx 有 ssl_stapling on; 等指令,但要链与解析都正确,配不好不如关------交给运维评估。
HSTS(示意):
nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
首次上线要确认没有 依赖明文 HTTP 的用户书签,否则最长一年内难撤回影响;includeSubDomains 影响子域,慎开。
13.2 mTLS 在 Nginx 边缘做校验(概念)
nginx
ssl_client_certificate /etc/nginx/certs/ca-chain.pem;
ssl_verify_client optional; # 或 require,视业务
通过后再把必要信息 proxy_set_header 带给后端(如证书序列号需在网关文档化,别直接传整 PEM 进 HTTP 头)。Spring 若不做 mTLS,就信任已鉴权的内网回源。
14. Spring Boot server.ssl 与转发:属性速查(3.3 语境)☕
下表是「认得名字、会搜文档 」用,精确键名以官方文档为准(Minor 升级会补属性)。
| 场景 | 常见配置方向 |
|---|---|
| PKCS12 路径 | server.ssl.key-store(或文档中的 bundle 写法) |
| 密钥库密码 | server.ssl.key-store-password(环境变量注入) |
| 密钥口令不同 | server.ssl.key-password |
| PEM 证书 | server.ssl.certificate(或 certificate-chain) |
| PEM 私钥 | server.ssl.certificate-private-key |
| 禁用旧协议 | server.ssl.enabled-protocols |
| 限制套件 | server.ssl.ciphers |
| 只信任客户端证 | server.ssl.client-auth(如需 mTLS) |
| 识别反代 HTTPS | server.forward-headers-strategy=framework 等 |
双端口 :有人喜欢 8080 仅内网、对外只暴露 8443 ------ 安全组与防火墙要和架构一致,别只留下 8080 给公网。
15. JVM 与 Java 出站的调试开关(仅排障短暂开)🔧
握手调试(日志极多,仅本机或灰度短时间):
text
-Djavax.net.debug=ssl:handshake:verbose
你会看到 ClientHello、选中套件、证书链加载等;抓完记得关,避免磁盘爆掉。
信任库 / 密钥库:
text
-Djavax.net.ssl.trustStore=C:\dev\corp-truststore.p12
-Djavax.net.ssl.trustStorePassword=secret
-Djavax.net.ssl.trustStoreType=PKCS12
误区别踩:
- 把
trustStore和keyStore(客户端证书)混在一个文件里管理,权限难审计。 - 生产关闭证书校验(
TrustAll)方便「联调」,结果忘了关上线。 - 只改 Nginx 证书却未 reload,导致新旧证并存、节点不一致。
16. 和【001】叠在一起:分层心智图 📌
以后排障可以在心里按层掰:
text
[ 浏览器 / 小程序 / Postman ]
│ DNS(【003】会讲)
▼
[ TCP 连接 ]
│ TLS 握手(本篇)
▼
[ HTTP/1.1 或 HTTP/2 上的请求/响应 ] ← 【001】
▼
[ 反代 / 网关 / Spring MVC / 业务 ]
现象归类:锁形报错、握手失败 → 先停在本篇;已经 200/401/502 → 回到【001】与业务日志。
17. 常见误区十条(口试 / 复盘可向团队念)📋
- 「HTTPS 就绝对安全」------ TLS 只保传输,鉴权弱、SQL 注入、账号泄露仍会发生。
- 「自签证书和 CA 证书只是心理安慰」------差在 公共信任根,小程序/公网用户不认自签。
- 「证书在 Nginx 更新了,Java 不用动」------若 Java 直连 旧入口或缓存了 OCSP/会话,要分路径讨论。
- 「PEM 好几个文件随便拼」------顺序错了链就断。
- 「禁 TLSv1.0 会掉所有用户」------ 2020 年代基本该禁,但要留 监控 看旧客户端占比。
- 「502 一定是 Java 挂了」------ SSL 在网关花式配置也会导致 握手失败或协议错误。
- 「开发关校验、生产复制同一镜像」------ 不要把 dev 的 trust 策略带进交付物。
- 「Cookie 不设 Secure 也能混 HTTPS」------现代浏览器对混用越来越严,按规范设。
- 「443 以外也能叫 HTTPS」------可以,但小程序/CDN 默认策略常卡 443,先读平台文档。
- 「证书没过期就没事」------还有 算法迁移、根证淘汰(历史上有)之类「日历外」事件,跟运维订阅公告。
小结 💡
- HTTPS 仍是【001】的 HTTP,只是先过 TLS:握手失败则业务层无感、日志可能只有 SSL 异常。
- 证书 看 SAN、有效期、链完整 ;fullchain 是运维口头禅也是有技术缘由的。
- TLS 1.3 更快更严;SNI 决定「同一 IP 上找对虚拟主机证书」。
- Spring Boot 可用 PKCS12/PEM 直开 TLS,但更多生产是 边缘终结 + Forwarded 头 + Boot 认反代。
- Java 客户端 牢记
cacerts/ 自定义 truststore 与PKIX系列错误。 - 排障:
curl -v、openssl s_client、浏览器证书详情三连,再分「握手 vs HTTP」。
下一篇(003)预告 🌐:TCP/IP 分层、超时与「后端接口为什么慢 / 为什么断」------和网关、Feign、数据库、线程池超时怎么对照着看。