我现在在后端项目上 使用自签证书 对域名 172.16.99.32:1043 生成了证书和密钥。并在 nginx 中启动服务使用这个
我使用 curl 加 -K 这个参数 可以成功调用 https 的接口
但是我的前端页面服务直接使用 python http.server 启动访问的时候 无法调用这个接口。报错net::ERR_CERT_AUTHORITY_INVALID
我该怎么解决呢。因为我只是为了 加密通信,且没有域名 。是不是可以在两端互相认证证书之类的呢?
解决方案概述 by-grok3
理解问题
您的问题是前端页面(通过 Python 的 http.server 提供服务)无法调用使用自签名证书的 HTTPS 接口(172.16.99.32:1043),而使用 curl -k 可以成功调用。错误为 net::ERR_CERT_AUTHORITY_INVALID,因为浏览器默认不信任自签名证书。由于您是为了开发环境中的加密通信,且没有域名,我们需要让浏览器信任该证书。
推荐解决方案:使用 mkcert
使用 mkcert 是最方便的方法,它会生成本地信任的证书,浏览器会自动识别。步骤如下:
- 安装 mkcert(在 macOS/Linux 上用
brew install mkcert,Windows 上从 GitHub 页面 下载)。 - 运行
mkcert -install安装本地 CA。 - 为您的 IP 生成证书:运行
mkcert 172.16.99.32。 - 在 nginx 中使用新生成的证书和密钥,更新配置并重启 nginx。
完成后,浏览器应该会信任该证书,前端可以正常访问 HTTPS 接口。
替代方案:手动信任证书
如果不使用 mkcert,可以手动将现有自签名证书添加到浏览器的信任存储:
- 导出证书文件(例如
server.crt)。 - 根据操作系统添加至信任存储:
- Windows:使用
certmgr.msc导入到“受信任的根证书颁发机构”。 - macOS:通过 Keychain Access 导入并设置为“始终信任”。
- Linux:添加到系统 CA 存储(如 Debian 的
/etc/ssl/certs/)。
- Windows:使用
- 重启浏览器后测试。
这个方法适合单机使用,但如果有多台机器或浏览器,操作会比较繁琐。
关于相互认证
您提到是否可以在两端相互认证证书。相互 TLS(mTLS)需要客户端和服务器都提供证书,但在开发环境中,浏览器通常不支持为任意网站提供客户端证书。由于您只需加密通信,信任服务器的证书已足够,mTLS 在此场景下可能不必要。
详细报告
背景与问题分析
您当前在后端项目中使用自签名证书为域名 172.16.99.32:1043 生成证书和密钥,并通过 nginx 提供 HTTPS 服务。使用 curl -k 可以成功调用接口,但前端页面(通过 Python 的 http.server 提供服务)访问时,浏览器报错 net::ERR_CERT_AUTHORITY_INVALID。这是因为自签名证书未由受信任的证书颁发机构(CA)签发,浏览器默认不信任。
curl -k 选项会跳过证书验证,因此能正常工作,但这在生产环境中不安全。对于浏览器,特别是在开发环境中,您希望加密通信且没有域名,解决方案需要让浏览器信任该证书。
解决方案详解
推荐方法:使用 mkcert 生成本地信任证书
mkcert 是一个专门为开发环境设计的工具,可以创建浏览器自动信任的证书。它通过安装一个本地 CA 并为指定主机(包括 IP 地址)生成证书来实现。
实施步骤
安装 mkcert:
- macOS/Linux:运行
brew install mkcert(需安装 Homebrew),或从 mkcert GitHub 页面 获取安装说明。 - Windows:从 GitHub 发布页面 下载二进制文件,并添加到系统 PATH。
- macOS/Linux:运行
安装本地 CA:
- 运行
mkcert -install,这会将 mkcert 的根证书添加到系统信任的 CA 列表中,浏览器会自动识别。
- 运行
为 IP 生成证书:
- 运行
mkcert 172.16.99.32,这会生成两个文件,例如172.16.99.32.pem(证书)和172.16.99.32-key.pem(密钥)。
- 运行
更新 nginx 配置:
- 在 nginx 配置文件中,替换现有的证书和密钥路径为 mkcert 生成的文件。例如:
1 2ssl_certificate /path/to/172.16.99.32.pem; ssl_certificate_key /path/to/172.16.99.32-key.pem; - 保存配置并重启 nginx(
sudo systemctl restart nginx或相应命令)。
- 在 nginx 配置文件中,替换现有的证书和密钥路径为 mkcert 生成的文件。例如:
测试:
- 访问前端页面,通过 JavaScript 或浏览器直接请求
https://172.16.99.32:1043,浏览器应不再报错。
- 访问前端页面,通过 JavaScript 或浏览器直接请求
优势
- mkcert 跨平台支持(Windows、macOS、Linux),适合团队开发。
- 支持为 IP 地址生成证书,符合您的需求(mkcert GitHub 页面 明确支持 IP)。
- 自动处理信任问题,无需手动为每个浏览器配置。
注意事项
确保 nginx 配置正确,且端口(1043)在防火墙中开放。证书适用于主机名,不涉及端口,端口由服务器配置处理。
替代方法:手动添加证书到信任存储
如果不使用 mkcert,可以手动将自签名证书添加到系统的信任证书存储中,但需要根据操作系统和浏览器进行配置。
实施步骤
导出证书:
- 找到现有自签名证书文件(例如
server.crt或server.pem)。如果没有,可以从 nginx 配置中提取。
- 找到现有自签名证书文件(例如
添加至信任存储:
- Windows:
- 打开
certmgr.msc(通过运行输入)。 - 导航至“受信任的根证书颁发机构” > “证书”。
- 右键点击“所有任务” > “导入”,选择证书文件,按照向导完成。
- 打开
- macOS:
- 打开 Keychain Access(通过启动台搜索)。
- 转到“文件” > “导入项目”,选择证书文件。
- 双击导入的证书,进入“信任”选项卡,将“When using this certificate”设置为“Always Trust”。
- Linux:
- 过程因发行版不同而异。例如,在 Debian/Ubuntu 上,将证书复制到
/etc/ssl/certs/,然后运行update-ca-certificates。
- 过程因发行版不同而异。例如,在 Debian/Ubuntu 上,将证书复制到
- Windows:
重启浏览器:
- 关闭并重新打开浏览器,确保新信任的证书生效。
测试:
- 访问
https://172.16.99.32:1043,确认错误消失。
- 访问
局限性
- 需要为每台机器和每个浏览器重复操作,适合单机开发,不适合团队。
- 配置过程可能因浏览器版本和操作系统不同而复杂。
关于相互认证(mTLS)
您提到是否可以在两端相互认证证书。这涉及到相互 TLS(mTLS),即客户端和服务器都提供证书进行身份验证。在生产环境中,这常用于内部网络以增强安全性。
然而,在您的开发场景中:
- 浏览器通常不支持为任意网站提供客户端证书,配置复杂。
- 您只需加密通信,信任服务器的证书已足够。
- mTLS 在开发环境中可能不必要,且实施成本较高。
因此,建议专注于让浏览器信任服务器证书,而非实现 mTLS。
额外考虑
CORS 问题
由于前端通过 Python 的 http.server 提供服务(通常为 HTTP,例如 http://localhost:8000),而后端为 HTTPS(https://172.16.99.32:1043),它们被视为不同来源(协议不同)。如果前端通过 JavaScript(如 fetch 或 XMLHttpRequest)请求后端,可能遇到 CORS 错误。
解决方法:
- 将前端也通过 HTTPS 提供服务(例如使用 mkcert 为前端生成证书)。
- 在后端(nginx)配置 CORS,允许来自前端的请求。例如,在 nginx 中添加:
1 2 3add_header Access-Control-Allow-Origin http://localhost:8000; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-Headers Authorization, Content-Type; - 测试后确保请求正常。
IP 地址证书的特殊性
证书通常为域名签发,但也支持 IP 地址。浏览器会接受 IP 地址的证书,只要信任该证书。mkcert 明确支持 IP 地址生成证书(mkcert GitHub 页面),因此不会出现问题。
总结
对于开发环境,推荐使用 mkcert 生成本地信任的证书,步骤简单且适合团队使用。如果不方便安装额外工具,可以手动将证书添加到信任存储,但操作较繁琐。关于相互认证,mTLS 在此场景下不必要,信任服务器证书已满足加密通信需求。