如何使用自签名证书正确设置我的离子(角度)开发机器?



我正在开发一个Ionic-Angular应用程序,由于清晰的文本流量,我遇到了很多问题。所以我决定即使在编码时也切换到https,但这并不容易。

我打开这个问题并提出我找到的答案以保持跟踪,如果您想这样做,希望能为您节省一些时间。

编辑:

我现在有一个证书生成脚本的存储库:https://github.com/ch4mpy/self-signed-certificate-generation

先决条件

需要开发计算机的主机名。此名称将在证书中声明,并且将使用此主机名访问 https 服务(URL 必须与https://[hostname]:...类似才能通过证书检查)。

如果您的网络还没有 DNS,则可以使用托管在开发计算机上的 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 "$1" ]
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="${1}"
echo "# key password: $KEY_PASSWORD"

if [ -z "$2" ]
then
if [ -z "$JAVA_HOME" ]
then
echo "ERROR: could not locate java home"
exit 1
else
JAVA=$JAVA_HOME
fi
else
JAVA=$2
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 "${3}" ]
then
HOST="$HOSTNAME"
else
HOST="${3}"
fi
echo "# host (certificate CN): $HOST"

if [ -z "${4}" ]
then
STORE_PASSWORD="$KEY_PASSWORD"
else
STORE_PASSWORD="${4}"
fi
echo "# store password : $STORE_PASSWORD"

if [ -z "${5}" ]
then
CERTIF_DIR="."
else
CERTIF_DIR="${5}"
fi
echo "# certificates directory path: $CERTIF_DIR"
CERTIF_DIR=$(echo $CERTIF_DIR | sed 's/\///g')

if [ -z "${6}" ]
then
CACERTS_PASSWORD="changeit"
else
CACERTS_PASSWORD="${6}"
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/JREcacerts文件中导入证书)(否则您将丢失以前的证书)。

可能需要管理员权限才能在 Java 的证书中导入证书。

在Windows上,Git Bash有所有的sedopensslkeytool在路径上。

将此证书导入为受信任的根证书颁发机构

如果将此证书添加到受信任的根颁发机构,则在导航 URL 时,您的浏览器将不会显示任何错误或警告,例如https://[hostname]:...

在 Windows 上,这可以通过certmgr.msc来完成(右键单击受信任的根颁发机构,然后导入)。如果您在其他操作系统上成功执行相同的操作,请发表评论。

将 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/app/src/main/res/在安卓工作室中的项目或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的经验,如果您可以正常工作,请随时发表评论或添加答案。

将后端配置为使用自签名证书通过 https 提供服务

井。。。这实际上取决于您使用的堆栈。几个示例:

  • 对于 Kestrel(在 Visual Studio 中调试的 .Net 应用程序),设置ASPNETCORE_Kestrel__Certificates__Default__PasswordASPNETCORE_Kestrel__Certificates__Default__Path,第二个指向[hostname]_self_signed.pfx
  • 对于 spring-boot,将[hostname]_self_signed.jks复制到src/main/resources/中并设置server.ssl属性
  • Keycloak具有全面的文档,可以使用自定义证书设置服务器
  • 如果您有其他后端类型正常工作,请发表评论

附言我用于 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.2Keycloak独立配置允许测试设备通过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

最新更新