【问题标题】:How to properly setup my Ionic (Angular) dev machine with self-signed certificate?如何使用自签名证书正确设置我的 Ionic (Angular) 开发机器?
【发布时间】:2020-12-31 14:08:30
【问题描述】:

我正在开发一个 Ionic-Angular 应用程序,但由于明文流量而面临很多问题。所以我决定在编码的同时切换到 https,但这并不容易。

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

【问题讨论】:

    标签: ionic-framework https ssl-certificate


    【解决方案1】:

    先决条件

    您的开发机器需要一个主机名。此名称将在证书中声明,并且将使用此主机名访问 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 然后 只需在第一次执行时复制/粘贴/运行所有输出命令,last command only(在 JDK / JRE cacerts 文件中导入证书)从第二次执行开始(否则您将丢失以前的证书)。

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

    在 Windows 上,Git Bash 在路径上包含所有 sedopensslkeytool

    将此证书导入为受信任的根权限

    如果您将此证书添加到受信任的根权限,您的浏览器在导航诸如 https://[hostname]:... 之类的 URL 时将不会显示错误或警告。

    在 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 项目中嵌入证书

    提醒: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" 添加到您的&lt;application &gt; 标签中

    在 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 拥有完整的文档到 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 2011-02-06
      • 2020-11-19
      • 1970-01-01
      • 2020-05-17
      相关资源
      最近更新 更多