如何使用自签名证书正确设置我的 Ionic (Angular) 开发机?
How to properly setup my Ionic (Angular) dev machine with self-signed certificate?
我正在开发 Ionic-Angular 应用程序,由于明文流量,我遇到了很多问题。所以我决定即使在编码时也切换到 https,但这并不容易。
我打开这个问题并提出我找到的答案,以备不时之需,如果您想这样做的话,希望能为您节省一些时间。
先决条件
您的开发机器需要一个主机名。此名称将在证书中声明,并且将使用此主机名访问 https 服务(URL 必须类似于 https://[hostname]:...
才能通过证书检查)。
如果您的网络还没有 DNS,您可以使用 dev-machine 上托管的 MaraDNS 之类的东西(请参阅 P.S。了解示例配置)。
生成各种格式的证书(和签名密钥)
self_signed_template.config:
[req]
default_bits = 2048
default_md = sha256
prompt = no
default_keyfile = [hostname]_self_signed_key.pem
encrypt_key = no
distinguished_name = dn
req_extensions = v3_req
x509_extensions = v3_req
[dn]
C = PF
ST = Tahiti
L = Papeete
O = c4-soft
emailAddress = ch4mp@c4-soft.com
CN = [hostname]
[v3_req]
subjectAltName = critical, @alt_names
basicConstraints = critical, CA:false
keyUsage = critical, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth, clientAuth
[alt_names]
DNS.1 = [hostname]
DNS.2 = localhost
DNS.3 = 10.0.2.2
self_signed.sh
#!/bin/bash
if [ -z "" ]
then
echo "Usage:"
echo ""
echo "self_signed.sh key_password [java_home] [hostname] [store_password] [certificates_directory_path] [cacerts_password]"
echo ""
echo " - java_home is defaulted to $JAVA_HOME"
echo " - hostname is defaulted to $HOSTNAME"
echo " - store_password is defaulted to key_password"
echo " - certificates_directory_path is defaulted to current diretory"
echo " - cacerts_password is defaulted to changeit"
echo ""
echo "Sample:"
echo "./self_signed.sh \"secr3!\" \"C:/Java/jdk1.8.0_281\" \"bravo-ch4mp\""
echo ""
exit 1
else
echo "#------------------------------------------"
echo "# This is a no-op script"
echo "# Copy / paste output to:"
echo "# - generate certificate files"
echo "# - import certificates into cacerts file"
echo "#------------------------------------------"
KEY_PASSWORD=""
echo "# key password: $KEY_PASSWORD"
if [ -z "" ]
then
if [ -z "$JAVA_HOME" ]
then
echo "ERROR: could not locate java home"
exit 1
else
JAVA=$JAVA_HOME
fi
else
JAVA=
fi
JAVA=$(echo $JAVA | sed 's/\/\//g')
echo "# java home: $JAVA"
if [ -f "${JAVA}/lib/security/cacerts" ]
then
# recent JDKs and JREs style
CACERTS="${JAVA}/lib/security/cacerts"
elif [ -f "${JAVA}/jre/lib/security/cacerts" ]
then
# legacy JDKs style (1.8 and older)
CACERTS="${JAVA}/jre/lib/security/cacerts"
else
echo "ERROR: could not locate cacerts under ${JAVA}"
exit 1
fi
echo "# cacerts path: $CACERTS"
if [ -z "" ]
then
HOST="$HOSTNAME"
else
HOST=""
fi
echo "# host (certificate CN): $HOST"
if [ -z "" ]
then
STORE_PASSWORD="$KEY_PASSWORD"
else
STORE_PASSWORD=""
fi
echo "# store password : $STORE_PASSWORD"
if [ -z "" ]
then
CERTIF_DIR="."
else
CERTIF_DIR=""
fi
echo "# certificates directory path: $CERTIF_DIR"
CERTIF_DIR=$(echo $CERTIF_DIR | sed 's/\/\//g')
if [ -z "" ]
then
CACERTS_PASSWORD="changeit"
else
CACERTS_PASSWORD=""
fi
echo "# cacerts password: $CACERTS_PASSWORD"
echo "#------------------------------------------"
fi
echo ""
rm -f ${HOST}_self_signed.config;
sed 's/\[hostname\]/'${HOST}'/g' "${CERTIF_DIR}/self_signed_template.config" > "${CERTIF_DIR}/${HOST}_self_signed.config"
echo openssl req -config \"${CERTIF_DIR}/${HOST}_self_signed.config\" -new -keyout \"${CERTIF_DIR}/${HOST}_self_signed_key.pem\" -out \"${CERTIF_DIR}/${HOST}_self_signed_cert.pem\" -reqexts v3_req
echo ""
echo openssl x509 -req -days 365 -extfile \"${CERTIF_DIR}/${HOST}_self_signed.config\" -in \"${CERTIF_DIR}/${HOST}_self_signed_cert.pem\" -extensions v3_req -signkey \"${CERTIF_DIR}/${HOST}_self_signed_key.pem\" -out \"${CERTIF_DIR}/${HOST}_self_signed.crt\"
echo ""
echo openssl pkcs12 -export -in \"${CERTIF_DIR}/${HOST}_self_signed.crt\" -inkey \"${CERTIF_DIR}/${HOST}_self_signed_key.pem\" -name ${HOST}_self_signed -password pass:${KEY_PASSWORD} -out \"${CERTIF_DIR}/${HOST}_self_signed.pfx\"
echo ""
echo \"${JAVA}/bin/keytool\" -importkeystore -srckeystore \"${CERTIF_DIR}/${HOST}_self_signed.pfx\" -srcstorepass \"${STORE_PASSWORD}\" -srcstoretype pkcs12 -srcalias ${HOST}_self_signed -destkeystore \"${CERTIF_DIR}/${HOST}_self_signed.jks\" -deststoretype PKCS12 -deststorepass ${STORE_PASSWORD} -destalias ${HOST}_self_signed
echo ""
echo \"${JAVA}/bin/keytool\" -importkeystore -srckeystore \"${CERTIF_DIR}/${HOST}_self_signed.pfx\" -srcstorepass \"${STORE_PASSWORD}\" -srcstoretype pkcs12 -srcalias ${HOST}_self_signed -destkeystore \"${CACERTS}\" -deststorepass ${CACERTS_PASSWORD} -destalias ${HOST}_self_signed
echo ""
然后 运行 类似 ./self_signed.sh "secr3!" C:/Java/jdk1.8.0_281
.
为每个 JDK/JRE 执行 ./self_signed.sh
,然后
只需复制/粘贴/运行 第一次执行时的所有输出命令和 仅最后一个命令(在 JDK / JRE cacerts
文件中导入证书)来自第二次执行(否则您将丢失以前的证书)。
可能需要管理员权限才能在 Java 的 cacerts 中导入证书。
在 windows 上,Git Bash 在路径上包含 sed
、openssl
和 keytool
。
将此证书导入为受信任的根授权机构
如果您将此证书添加到受信任的根授权机构,您的浏览器在导航 https://[hostname]:...
.
等 URL 时将不会显示任何错误或警告
在 windows 上,这可以通过 certmgr.msc
完成(右键单击受信任的根权限,然后导入)。如果您在其他 OS.
上成功执行相同操作,请发表评论
配置 Ionic-Angular 使用此证书通过 https 服务
编辑angular.json
设置your-project/architect/serve/options/
下的“sslCert”和“sslKey”,分别指向之前生成的[hostname]_self_signed.crt
和[hostname]_self_signed_key.pem
。
这足以在运行宁ionic serve --ssl --host=[hostname]
或ionic capacitor run android -l --ssl --host=[hostname]
时选择正确的证书
在 Android 项目中嵌入证书
提醒:android 资源文件夹在您的项目下 android/app/src/main/res/
或 Android Studio
中的 app/res/
首先,将 [hostname]_self_signed.crt
复制到 raw
资源,如果有的话,将 -
替换为主机名中的 _
。
在 xml 资源中创建 network_security_config.xml
(小心修改主机名)
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="@raw/[hostname]_self_signed"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
重要说明:如果您的所有流量都通过 https 提供,则应将 cleartextTrafficPermitted
设置为 false(这是自 Android 9 以来的默认值)。至少考虑为产品构建这样做。
最后,编辑 AndroidManifest.xml
并将 android:networkSecurityConfig="@xml/network_security_config"
添加到您的 <application >
标签
在 iOS 项目中嵌入证书
我没有使用 iOS 的经验,如果您能正常使用,请随时发表评论或添加答案。
将您的后端配置为使用 self-signed 证书通过 https 提供服务
嗯...这真的取决于您使用的堆栈。几个样本:
- 对于 Kestrel(在 Visual Studio 中调试的 .Net 应用程序),设置
ASPNETCORE_Kestrel__Certificates__Default__Password
和 ASPNETCORE_Kestrel__Certificates__Default__Path
,第二个指向 [hostname]_self_signed.pfx
- 对于spring-boot,将
[hostname]_self_signed.jks
复制到src/main/resources/
并设置server.ssl
属性
- Keycloak 具有 setup the server 的综合文档和自定义证书
- 如果其他后端类型正常工作,请发表评论
P.S. 我用于 MaraDNS 的 dwood3rc.txt
文件:
#upstream_servers = {}
#upstream_servers["."]="8.8.8.8, 8.8.4.4" # Servers we connect to
root_servers = {}
# ICANN DNS root servers
root_servers["."]="198.41.0.4, 199.9.14.201, 192.33.4.12, 199.7.91.13,"
root_servers["."]+="192.203.230.10, 192.5.5.241, 192.112.36.4, "
root_servers["."]+="198.97.190.53, 192.36.148.17, 192.58.128.30, "
root_servers["."]+="193.0.14.129, 199.7.83.42, 202.12.27.33"
# local DNS server
root_servers["bravo-ch4mp."]="192.168.1.181"
root_servers["local."]="192.168.1.181"
# The IP this program has
bind_address="127.0.0.1, 192.168.1.181, 192.168.1.132"
# The IPs allowed to connect and use the cache
recursive_acl = "127.0.0.1/16, 192.168.0.1/16"
chroot_dir = "/etc/maradns"
# This is the file Deadwood uses to read the cache to and from disk
cache_file = "dw_cache_bin"
filter_rfc1918 = 0
ip4 = {}
ip4["bravo-ch4mp."] = "192.168.1.181"
ip6 = {}
一旦 DNS 服务器在我的开发机器上启动 (net start deadwood
)(并且还配置了防火墙...),我将客户端配置为将其用作主 DNS(编辑不需要的 wifi 网络属性有根设备)等瞧!
P.S.2 Keycloak 独立配置允许测试设备通过 https
连接到 OpenId 端点
将[hostname]_self_signed.jks
复制到standalone/configuration/
。
编辑 standalone/configuration/standalone.xml
以将 ${jboss.bind.address:127.0.0.1}
替换为 ${jboss.bind.address:0.0.0.0}
。保存并关闭。
使用 bin/standalone[.bat|.sh]
启动 Keycloak,然后使用 bin/jboss-cli[.bat|.sh]
:
connect
/subsystem=keycloak-server/spi=hostname/provider=default:write-attribute(name=properties.frontendUrl,value="https://[hostname]:8443/auth")
/core-service=management/security-realm=UndertowRealm:add()
/core-service=management/security-realm=UndertowRealm/server-identity=ssl:add(keystore-path=[hostname]_self_signed.jks, keystore-relative-to=jboss.server.config.dir, keystore-password=[keystore_password])
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=security-realm, value=UndertowRealm)
reload
我正在开发 Ionic-Angular 应用程序,由于明文流量,我遇到了很多问题。所以我决定即使在编码时也切换到 https,但这并不容易。
我打开这个问题并提出我找到的答案,以备不时之需,如果您想这样做的话,希望能为您节省一些时间。
先决条件
您的开发机器需要一个主机名。此名称将在证书中声明,并且将使用此主机名访问 https 服务(URL 必须类似于 https://[hostname]:...
才能通过证书检查)。
如果您的网络还没有 DNS,您可以使用 dev-machine 上托管的 MaraDNS 之类的东西(请参阅 P.S。了解示例配置)。
生成各种格式的证书(和签名密钥)
self_signed_template.config:
[req]
default_bits = 2048
default_md = sha256
prompt = no
default_keyfile = [hostname]_self_signed_key.pem
encrypt_key = no
distinguished_name = dn
req_extensions = v3_req
x509_extensions = v3_req
[dn]
C = PF
ST = Tahiti
L = Papeete
O = c4-soft
emailAddress = ch4mp@c4-soft.com
CN = [hostname]
[v3_req]
subjectAltName = critical, @alt_names
basicConstraints = critical, CA:false
keyUsage = critical, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth, clientAuth
[alt_names]
DNS.1 = [hostname]
DNS.2 = localhost
DNS.3 = 10.0.2.2
self_signed.sh
#!/bin/bash
if [ -z "" ]
then
echo "Usage:"
echo ""
echo "self_signed.sh key_password [java_home] [hostname] [store_password] [certificates_directory_path] [cacerts_password]"
echo ""
echo " - java_home is defaulted to $JAVA_HOME"
echo " - hostname is defaulted to $HOSTNAME"
echo " - store_password is defaulted to key_password"
echo " - certificates_directory_path is defaulted to current diretory"
echo " - cacerts_password is defaulted to changeit"
echo ""
echo "Sample:"
echo "./self_signed.sh \"secr3!\" \"C:/Java/jdk1.8.0_281\" \"bravo-ch4mp\""
echo ""
exit 1
else
echo "#------------------------------------------"
echo "# This is a no-op script"
echo "# Copy / paste output to:"
echo "# - generate certificate files"
echo "# - import certificates into cacerts file"
echo "#------------------------------------------"
KEY_PASSWORD=""
echo "# key password: $KEY_PASSWORD"
if [ -z "" ]
then
if [ -z "$JAVA_HOME" ]
then
echo "ERROR: could not locate java home"
exit 1
else
JAVA=$JAVA_HOME
fi
else
JAVA=
fi
JAVA=$(echo $JAVA | sed 's/\/\//g')
echo "# java home: $JAVA"
if [ -f "${JAVA}/lib/security/cacerts" ]
then
# recent JDKs and JREs style
CACERTS="${JAVA}/lib/security/cacerts"
elif [ -f "${JAVA}/jre/lib/security/cacerts" ]
then
# legacy JDKs style (1.8 and older)
CACERTS="${JAVA}/jre/lib/security/cacerts"
else
echo "ERROR: could not locate cacerts under ${JAVA}"
exit 1
fi
echo "# cacerts path: $CACERTS"
if [ -z "" ]
then
HOST="$HOSTNAME"
else
HOST=""
fi
echo "# host (certificate CN): $HOST"
if [ -z "" ]
then
STORE_PASSWORD="$KEY_PASSWORD"
else
STORE_PASSWORD=""
fi
echo "# store password : $STORE_PASSWORD"
if [ -z "" ]
then
CERTIF_DIR="."
else
CERTIF_DIR=""
fi
echo "# certificates directory path: $CERTIF_DIR"
CERTIF_DIR=$(echo $CERTIF_DIR | sed 's/\/\//g')
if [ -z "" ]
then
CACERTS_PASSWORD="changeit"
else
CACERTS_PASSWORD=""
fi
echo "# cacerts password: $CACERTS_PASSWORD"
echo "#------------------------------------------"
fi
echo ""
rm -f ${HOST}_self_signed.config;
sed 's/\[hostname\]/'${HOST}'/g' "${CERTIF_DIR}/self_signed_template.config" > "${CERTIF_DIR}/${HOST}_self_signed.config"
echo openssl req -config \"${CERTIF_DIR}/${HOST}_self_signed.config\" -new -keyout \"${CERTIF_DIR}/${HOST}_self_signed_key.pem\" -out \"${CERTIF_DIR}/${HOST}_self_signed_cert.pem\" -reqexts v3_req
echo ""
echo openssl x509 -req -days 365 -extfile \"${CERTIF_DIR}/${HOST}_self_signed.config\" -in \"${CERTIF_DIR}/${HOST}_self_signed_cert.pem\" -extensions v3_req -signkey \"${CERTIF_DIR}/${HOST}_self_signed_key.pem\" -out \"${CERTIF_DIR}/${HOST}_self_signed.crt\"
echo ""
echo openssl pkcs12 -export -in \"${CERTIF_DIR}/${HOST}_self_signed.crt\" -inkey \"${CERTIF_DIR}/${HOST}_self_signed_key.pem\" -name ${HOST}_self_signed -password pass:${KEY_PASSWORD} -out \"${CERTIF_DIR}/${HOST}_self_signed.pfx\"
echo ""
echo \"${JAVA}/bin/keytool\" -importkeystore -srckeystore \"${CERTIF_DIR}/${HOST}_self_signed.pfx\" -srcstorepass \"${STORE_PASSWORD}\" -srcstoretype pkcs12 -srcalias ${HOST}_self_signed -destkeystore \"${CERTIF_DIR}/${HOST}_self_signed.jks\" -deststoretype PKCS12 -deststorepass ${STORE_PASSWORD} -destalias ${HOST}_self_signed
echo ""
echo \"${JAVA}/bin/keytool\" -importkeystore -srckeystore \"${CERTIF_DIR}/${HOST}_self_signed.pfx\" -srcstorepass \"${STORE_PASSWORD}\" -srcstoretype pkcs12 -srcalias ${HOST}_self_signed -destkeystore \"${CACERTS}\" -deststorepass ${CACERTS_PASSWORD} -destalias ${HOST}_self_signed
echo ""
然后 运行 类似 ./self_signed.sh "secr3!" C:/Java/jdk1.8.0_281
.
为每个 JDK/JRE 执行 ./self_signed.sh
,然后
只需复制/粘贴/运行 第一次执行时的所有输出命令和 仅最后一个命令(在 JDK / JRE cacerts
文件中导入证书)来自第二次执行(否则您将丢失以前的证书)。
可能需要管理员权限才能在 Java 的 cacerts 中导入证书。
在 windows 上,Git Bash 在路径上包含 sed
、openssl
和 keytool
。
将此证书导入为受信任的根授权机构
如果您将此证书添加到受信任的根授权机构,您的浏览器在导航 https://[hostname]:...
.
在 windows 上,这可以通过 certmgr.msc
完成(右键单击受信任的根权限,然后导入)。如果您在其他 OS.
配置 Ionic-Angular 使用此证书通过 https 服务
编辑angular.json
设置your-project/architect/serve/options/
下的“sslCert”和“sslKey”,分别指向之前生成的[hostname]_self_signed.crt
和[hostname]_self_signed_key.pem
。
这足以在运行宁ionic serve --ssl --host=[hostname]
或ionic capacitor run android -l --ssl --host=[hostname]
在 Android 项目中嵌入证书
提醒:android 资源文件夹在您的项目下 android/app/src/main/res/
或 Android Studio
app/res/
首先,将 [hostname]_self_signed.crt
复制到 raw
资源,如果有的话,将 -
替换为主机名中的 _
。
在 xml 资源中创建 network_security_config.xml
(小心修改主机名)
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="@raw/[hostname]_self_signed"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
重要说明:如果您的所有流量都通过 https 提供,则应将 cleartextTrafficPermitted
设置为 false(这是自 Android 9 以来的默认值)。至少考虑为产品构建这样做。
最后,编辑 AndroidManifest.xml
并将 android:networkSecurityConfig="@xml/network_security_config"
添加到您的 <application >
标签
在 iOS 项目中嵌入证书
我没有使用 iOS 的经验,如果您能正常使用,请随时发表评论或添加答案。
将您的后端配置为使用 self-signed 证书通过 https 提供服务
嗯...这真的取决于您使用的堆栈。几个样本:
- 对于 Kestrel(在 Visual Studio 中调试的 .Net 应用程序),设置
ASPNETCORE_Kestrel__Certificates__Default__Password
和ASPNETCORE_Kestrel__Certificates__Default__Path
,第二个指向[hostname]_self_signed.pfx
- 对于spring-boot,将
[hostname]_self_signed.jks
复制到src/main/resources/
并设置server.ssl
属性 - Keycloak 具有 setup the server 的综合文档和自定义证书
- 如果其他后端类型正常工作,请发表评论
P.S. 我用于 MaraDNS 的 dwood3rc.txt
文件:
#upstream_servers = {}
#upstream_servers["."]="8.8.8.8, 8.8.4.4" # Servers we connect to
root_servers = {}
# ICANN DNS root servers
root_servers["."]="198.41.0.4, 199.9.14.201, 192.33.4.12, 199.7.91.13,"
root_servers["."]+="192.203.230.10, 192.5.5.241, 192.112.36.4, "
root_servers["."]+="198.97.190.53, 192.36.148.17, 192.58.128.30, "
root_servers["."]+="193.0.14.129, 199.7.83.42, 202.12.27.33"
# local DNS server
root_servers["bravo-ch4mp."]="192.168.1.181"
root_servers["local."]="192.168.1.181"
# The IP this program has
bind_address="127.0.0.1, 192.168.1.181, 192.168.1.132"
# The IPs allowed to connect and use the cache
recursive_acl = "127.0.0.1/16, 192.168.0.1/16"
chroot_dir = "/etc/maradns"
# This is the file Deadwood uses to read the cache to and from disk
cache_file = "dw_cache_bin"
filter_rfc1918 = 0
ip4 = {}
ip4["bravo-ch4mp."] = "192.168.1.181"
ip6 = {}
一旦 DNS 服务器在我的开发机器上启动 (net start deadwood
)(并且还配置了防火墙...),我将客户端配置为将其用作主 DNS(编辑不需要的 wifi 网络属性有根设备)等瞧!
P.S.2 Keycloak 独立配置允许测试设备通过 https
连接到 OpenId 端点将[hostname]_self_signed.jks
复制到standalone/configuration/
。
编辑 standalone/configuration/standalone.xml
以将 ${jboss.bind.address:127.0.0.1}
替换为 ${jboss.bind.address:0.0.0.0}
。保存并关闭。
使用 bin/standalone[.bat|.sh]
启动 Keycloak,然后使用 bin/jboss-cli[.bat|.sh]
:
connect
/subsystem=keycloak-server/spi=hostname/provider=default:write-attribute(name=properties.frontendUrl,value="https://[hostname]:8443/auth")
/core-service=management/security-realm=UndertowRealm:add()
/core-service=management/security-realm=UndertowRealm/server-identity=ssl:add(keystore-path=[hostname]_self_signed.jks, keystore-relative-to=jboss.server.config.dir, keystore-password=[keystore_password])
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=security-realm, value=UndertowRealm)
reload