为Android配置允许自签证书认证
最近在用 UniApp 开发一个混合项目,后端部署在内网,用的是自己签的 HTTPS 证书。打包成apk包后,测试了一下请求直接挂掉,报了证书验证不通过的错误:
Trust anchor for certification path not found.为解决这个问题,我们需要让Android信任我们自己签的 HTTPS 证书。
为什么会存在这个问题?
Android 从 7.0 开始,默认只信任系统内置的权威证书(比如 Let's Encrypt、DigiCert 这些)。
自己生成的证书,它不认识,直接拒绝连接。
同时,Android 9+ 默认禁止所有 HTTP 明文请求(除非你特别允许)。
经过调研主要有两种办法,一是在Android的系统设置中安装自签证书,但这种办法不太容易实现,毕竟当APP使用面比较广的时候,你是不能给所有用户都装一遍的。第二种就是让apk内部去信任自签证书。
利用Network Security Config解决自签SSL认证
从服务器中导出证书
将证书文件放置在Android项目资源文件夹中
编写Network Security Config文件
在AndroidManifest.xml中使用Network Security Config文件
# 下载证书 假设IP为192.168.1.100
openssl s_client -connect 192.168.1.100:443 < /dev/null | openssl x509 > my-server.crt
# 移动证书到指定位置
mv my-server.crt /path/to/res/raw/
# 创建Network Security Config文件
cat > /path/to/android/res/xml/network_security_config.xml <<EOF
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 信任自签证书的内网地址 -->
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="false">192.168.1.100</domain>
<trust-anchors>
<certificates src="@raw/my-server" />
</trust-anchors>
</domain-config>
<!-- 允许特定域名使用 HTTP(仅当无法使用 HTTPS 时) -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">www.xxx.cn</domain>
</domain-config>
<!-- 全局默认:其他所有请求走系统 CA 验证,禁止 HTTP -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<!-- 调试时允许用户证书(仅 debug 包生效) -->
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
EOF在AndroidManifest.xml中追加内容:
......
<application
......
android:networkSecurityConfig="@xml/network_security_config">
......
</application>
......如何自签证书?
在开发、测试或内网环境中,自签证书是一种快速搭建 HTTPS 服务的常用方式。以下是基于 OpenSSL 的自签证书生成完整流程,支持指定域名与 IP 地址,适用于如 Nginx、Apache 等 Web 服务器。
准备一个配置文件 server.conf ,内容如下:
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[dn]
CN = 192.168.1.100
[v3_req]
subjectAltName = @alt_names
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[alt_names]
DNS.1 = www.xxx.cn
# DNS.2 = xxx.xxx.xxx
IP.1 = 192.168.1.100
# IP.2 = xx.xx.xx.xx说明:
CN:证书的通用名称,通常填写服务器 IP 或主域名。
DNS.1和DNS.2:允许访问的域名。
IP.1和IP.2:支持的 IP 地址。
keyUsage:定义证书用途,支持签名与加密。
subjectAltName:扩展字段,允许证书包含多个域名或 IP。
而后根据是否有现成私钥,选择以下任一命令:
✅ 有私钥(如已生成 privkey.key):
openssl req -new -x509 \
-key privkey.key \
-out fullchain.crt \
-days 365 \
-config server.conf \
-extensions v3_req🔐 无私钥(一键生成私钥 + 证书):
openssl req -x509 -nodes -days 365 \
-newkey rsa:4096 \
-keyout privkey.key \
-out fullchain.crt \
-config server.conf \
-extensions v3_req输出文件说明:
privkey.key:私钥文件,务必妥善保管。
fullchain.crt:自签名证书文件,可直接用于 Web 服务器配置。
注意事项
浏览器会警告:自签证书不被信任,浏览器会提示“不安全”。可手动信任证书以消除警告。
仅限测试/内部使用:不要用于生产环境对外服务,否则可能引发安全风险。
证书有效期:默认 365 天,可按需修改
-days参数。私钥安全:私钥文件切勿泄露,建议设置权限
600:chmod 600 privkey.key