
HTTPS 在解决什么问题 ✉在HTTP上链路中的设备若能看到你的流量就能读到 URL含敏感 query、Header、Body含 token——敏感凭证更应放 Header 而非 query。HTTPS HTTP over TLSTLS 主要负责三件事和「机密性 / 完整性 / 身份」对应机密性应用数据用协商出的对称密钥加密窃听者拿到的是密文。完整性现代套件多用AEAD篡改更容易被对端拒收或校验失败。身份对服务端而言最显眼服务端用X.509 证书绑定域名及公钥客户端验证链与主机名后才相信「当前连接对端是该域名背后的服务」。还要知道两个「周边」问题混合内容Mixed Content页面是 HTTPS但页面里的脚本、接口、图片还用http://去拉浏览器可能拦截或降级处理表现为「线上环境只有部分资源失败」。前后端联调时统一入口协议很关键。HSTSHTTP 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。常见存放形态形态说明PEMBase64 -----BEGIN CERTIFICATE-----头尾可读文本可链式拼接多个证书。DER二进制扩展名不一定是.der有时.crt既是 PEM 又是 DER需用openssl x509 -in file -text -noout试读。PKCS#12.p12 / .pfx一个文件里常含私钥 证书链 密码保护Javakeytool、Springkey-store-type: PKCS12都爱用它。2.1 字段里你最该盯的概念你需要知道的SANSubject Alternative Name现代浏览器校验主名看 SAN仅 CNCommon 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.2TLS 1.3典型往返RTT完整握手常见2-RTT外加 TCP1-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 SNIServer 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——最常见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证书文件 私钥文件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 常用server: forward-headers-strategy: framework或native——具体取值请对照当前 minor文档与你们网关实际发的头。没配时常见 bug 是登录后重定向成http://导致无限跳或 Cookie 丢失。5. 反向代理终结 TLS更常见的生产形态5.1 典型拓扑浏览器 --HTTPS-- 云 LB / Nginx / Ingress --HTTP-- Spring Boot :8080 \--HTTPS mTLS-- 少数场景TLS 在「边缘」终结内网回源可走明文 HTTP配合安全组/专线策略。你的Java 日志里 RemoteAddr往往是反代 IP真实客户端在X-Forwarded-For里注意伪造链信任边界以网关抹写为准。5.2 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.2keytool看库、导入根证示例# 列出 cacerts 里别名路径随 JDK 安装变 keytool -list -keystore %JAVA_HOME%\lib\security\cacerts -storepass changeit企业根证书导入示例别名自定keytool -importcert -noprompt -alias corp-root -file corp-root.pem -keystore %JAVA_HOME%\lib\security\cacerts -storepass changeit注意改系统cacerts影响整台机所有 Java 进程很多公司改为启动时挂自定义 truststore或容器镜像层统一管理。自定义 truststore 启动-Djavax.net.ssl.trustStoreE:/dev/corp-truststore.p12 -Djavax.net.ssl.trustStorePasswordyourSecret -Djavax.net.ssl.trustStoreTypePKCS126.3 典型异常与含义异常 / 日志关键字更可能原因PKIX path building failed不信任颁发链、缺根/中间、或连错环境测网证书打生产域名CertificateExpiredException证书过期CertificateNotYetValidException本机时间不对或证书未生效No subject alternative DNS name matching访问的 Host 不在证书 SANjavax.net.ssl.SSLHandshakeException协议/套件/证书错误的大箩筐需打开-Djavax.net.debugssl:handshake仅排障短暂开SunCertPathBuilderException常与 PKIX 同类链构造失败6.4 框架层RestTemplate / RestClient / Feign公网 CA一般零配置。私有 CA运维发根证→ 进 truststore推荐→ 再谈代码。「开发环境跳过校验」类TrustManager不要复制进生产代码评审应拦。Feign / HttpClient 若单独配了 SSL 上下文要确认没有覆盖默认的 SNI 行为少数老配置会踩坑。7. 联调与排障命令、流程与表 ✅7.1 curl看握手与证书Windows 可把管道后换成findstrcurl -v https://api.example.com/actuator/health 21 | findstr /i subject issuer expire SSL certificate指定解析排除 DNS 捣乱curl -v --resolve api.example.com:443:203.0.113.10 https://api.example.com/7.2 openssl s_client有 OpenSSL 的环境openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts /dev/null关注证书链有几张、Verify return code是否 0、subjectCN/ 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是否包含企业根JVMTLS 版本是否过严或过旧。仅部分移动网络失败想到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或 Windowshosts把local.test指到127.0.0.1用 SAN 覆盖该名字OpenSSL 命令各版本用req v3_reqsubjectAltName配置块此处给思路命令以你本机 OpenSSL 手册为准生成私钥CSR自签SAN 含DNS:local.test、DNS:localhost。Springserver.ssl.certificate/certificate-private-key指向生成文件server.port8443。浏览器首次仍会红屏——导入自签为受信任根或每次点高级继续团队规范通常禁止把这种证书用于联调小程序。8.2 开发利器 mkcert可选mkcert在开发机上生成本地受信 CA浏览器少红屏仍非公网方案上线与小程序无关。8.3 「与生产一致」的路径尽量用测试环境已申请的正式域正式证书或 staging连接到类生产网关减少「本地自签一切正常、上云全挂」的落差。9. 双向 TLSmTLS——知道边界即可 部分开放银行 / 企业 B2B要求客户端也交证书服务端校验「你是谁」。此时除服务端server.ssl.*trust-store 配合作方根或伙伴客户端认证配置外客户端要配keyStore自己的证书私钥。细节强烈依赖对方接口文档与你们网关是否 offload这里只提醒遇到「要交客户端证书」的需求别在业务代码里硬编码私钥路径密码交给配置中心与密钥托管。10. 小程序 / 开放平台的「合法域名」——和 HTTPS 的关系 不同平台细则会变开发时可按下面自查以微信等官方文档为准这里列工程常识接口域名必须是HTTPS小程序里request合法域名列表。证书链完整、TLS 版本与套件满足平台最低要求旧版文档常写不支持 SSLv3 等需读当期说明。域名已加到控制台「合法域名」且与证书 SAN一致。部分能力要求ICP 备案、业务域名校验文件等——与纯 TLS 不同但排障时一起查。「后端同事说接口OK小程序不通」——先手机浏览器打开同一 URL 看证书再用开发者工具 Network最后核对控制后台域名配置。11. OpenSSL带 SAN 的自签与 CSR 思路可复制骨架下面是一段「思路骨架」用独立配置文件把SAN写清楚避免证书只有CNlocalhost、没有 SAN被 Chrome 等直接标红。具体命令以你机器上OpenSSL 3.x / 1.1.1文档为准路径自行替换。第一步写openssl-san.cnf示例[ 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 自签证书示例命令序列openssl req -new -x509 -nodes -days 365 -keyout local.test.key -out local.test.crt -config openssl-san.cnf -extensions v3_req生成的local.test.crtlocal.test.key可交给 Spring Bootserver.ssl.certificate/certificate-private-key或先拼成 p12 再用key-store。记得在hosts里把local.test指到本机否则浏览器用别的名字访问仍会报域名不匹配。验证书内容看 SAN 是否在openssl x509 -in local.test.crt -noout -text | findstr /i Subject Alternative Name DNSLinux / 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 安全基线示意具体以你们等保/基线为准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示意add_header Strict-Transport-Security max-age31536000; includeSubDomains always;首次上线要确认没有依赖明文 HTTP 的用户书签否则最长一年内难撤回影响includeSubDomains影响子域慎开。13.2 mTLS 在 Nginx 边缘做校验概念ssl_client_certificate /etc/nginx/certs/ca-chain.pem; ssl_verify_client optional; # 或 require视业务通过后再把必要信息proxy_set_header带给后端如证书序列号需在网关文档化别直接传整 PEM 进 HTTP 头。Spring 若不做 mTLS就信任已鉴权的内网回源。14. Spring Bootserver.ssl与转发属性速查3.3 语境☕下表是「认得名字、会搜文档」用精确键名以官方文档为准Minor 升级会补属性。场景常见配置方向PKCS12 路径server.ssl.key-store或文档中的 bundle 写法密钥库密码server.ssl.key-store-password环境变量注入密钥口令不同server.ssl.key-passwordPEM 证书server.ssl.certificate或certificate-chainPEM 私钥server.ssl.certificate-private-key禁用旧协议server.ssl.enabled-protocols限制套件server.ssl.ciphers只信任客户端证server.ssl.client-auth如需 mTLS识别反代 HTTPSserver.forward-headers-strategyframework等双端口有人喜欢8080仅内网、对外只暴露8443—— 安全组与防火墙要和架构一致别只留下 8080 给公网。15. JVM 与 Java 出站的调试开关仅排障短暂开握手调试日志极多仅本机或灰度短时间-Djavax.net.debugssl:handshake:verbose你会看到ClientHello、选中套件、证书链加载等抓完记得关避免磁盘爆掉。信任库 / 密钥库-Djavax.net.ssl.trustStoreC:\dev\corp-truststore.p12 -Djavax.net.ssl.trustStorePasswordsecret -Djavax.net.ssl.trustStoreTypePKCS12误区别踩把trustStore和keyStore客户端证书混在一个文件里管理权限难审计。生产关闭证书校验TrustAll方便「联调」结果忘了关上线。只改 Nginx 证书却未reload导致新旧证并存、节点不一致。16. 和【001】叠在一起分层心智图 以后排障可以在心里按层掰[ 浏览器 / 小程序 / 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、数据库、线程池超时怎么对照着看。分类: Java实战连载从基础到SpringBoot全栈交付标签: HTTP, Java, TSL免责声明本内容来自平台创作者博客园系信息发布平台仅提供信息存储空间服务。好文要顶 关注我 收藏该文 微信分享杨凯凡粉丝 - 2 关注 - 0加关注20升级成为会员« 上一篇 【001】研发要搞懂的 HTTP方法、状态码、Header 与一次请求的链路» 下一篇 【003】TCP/IP 分层与「超时」在后端接口里的表现posted 2026-04-17 11:13 杨凯凡 阅读(264) 评论(1) 收藏 举报