OpenSSL 自签名证书生成脚本(免交互脚本、Nginx 配置、Chrome信任)

前言

在 Linux 下,测试或局域网环境。使用 OpenSSL 生成自签名证书 、Nginx 配置及 Chrome 浏览器信任。

安装 openssl

yum install -y openssl openssl-devel vim

# 或

apt-get install -y openssl vim

方式一

使用 FiloSottile/mkcert 项目生成证书,这个支持全平台生成。

介绍

mkcert 是一个简单的工具,用于制作本地信任的开发证书。它不需要配置。

简化我们在本地搭建 https 环境的复杂性,无需操作繁杂的 openssl 实现自签证书了,这个小程序就可以帮助我们自签证书,在本机使用还会自动信任 CA,非常方便。

使用来自真实证书颁发机构 (CA) 的证书进行开发可能很危险或不可能(对于 example.test​、localhost ​或 之类的主机 127.0.0.1​),但自签名证书会导致信任错误。管理您自己的 CA 是最好的解决方案,但通常涉及神秘的命令、专业知识和手动步骤。

mkcert 在系统根存储中自动创建并安装本地 CA,并生成本地信任的证书。mkcert 不会自动配置服务器以使用证书,但这取决于您。

下载

本实验使用 Windows 10 操作系统进行演示说明。mkcert 也支持其他噶平台的安装与使用,自行下载对应的版本安装即可。

image-20210813104529759

安装配置

调出命令提示符

image-20210813105729689

安装 mkcert

输入命令 ,安装 mkcert,将 CA 证书加入本地可信 CA:

mkcert-v1.4.3-windows-amd64.exe -install

使用此命令,就能帮助我们将 mkcert 使用的根证书加入了本地可信 CA 中,以后由该 CA 签发的证书在本地都是可信的。

image-20210813105958556

安装成功成功。提示创建一个新的本地 CA,本地 CA 现在已安装在系统信任存储中。

image-20210813110100362

测试是否安装成功

C:\>mkcert-v1.4.3-windows-amd64.exe --help
Usage of mkcert:

        $ mkcert -install
        Install the local CA in the system trust store.

        $ mkcert example.org
        Generate "example.org.pem" and "example.org-key.pem".

        $ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
        Generate "example.com+4.pem" and "example.com+4-key.pem".

        $ mkcert "*.example.it"
        Generate "_wildcard.example.it.pem" and "_wildcard.example.it-key.pem".

        $ mkcert -uninstall
        Uninstall the local CA (but do not delete it).

Advanced options:

        -cert-file FILE, -key-file FILE, -p12-file FILE
            Customize the output paths.

        -client
            Generate a certificate for client authentication.

        -ecdsa
            Generate a certificate with an ECDSA key.

        -pkcs12
            Generate a ".p12" PKCS #12 file, also know as a ".pfx" file,
            containing certificate and key for legacy applications.

        -csr CSR
            Generate a certificate based on the supplied CSR. Conflicts with
            all other flags and arguments except -install and -cert-file.

        -CAROOT
            Print the CA certificate and key storage location.

        $CAROOT (environment variable)
            Set the CA certificate and key storage location. (This allows
            maintaining multiple local CAs in parallel.)

        $TRUST_STORES (environment variable)
            A comma-separated list of trust stores to install the local
            root CA into. Options are: "system", "java" and "nss" (includes
            Firefox). Autodetected by default.


C:\>

image-20210813111118157

查看 CA 证书存放位置

mkcert-v1.4.3-windows-amd64.exe -CAROOT

image-20210813110534373

image-20210813111715875
按“Windows 键 +R”调出运行框,输入 certmgr.msc​ 命令。打开证书控制台。

image-20210813112136872

image-20210813112422780

image-20210813112617233

生成自签证书

直接跟多个要签发的域名或 ip 就行了,比如签发一个仅本机访问的证书(可以通过 127.0.0.1​ 和 localhost​,以及 ipv6 地址 ::1​ 访问)

需要在局域网内测试 https 应用,这种环境可能不对外,因此也无法使用像 Let's encrypt​ 这种免费证书的方案给局域网签发一个可信的证书,而且 Let's encrypt​ 本身也不支持认证 Ip。

证书可信的三个要素:

  • 由可信的 CA 机构签发
  • 访问的地址跟证书认证地址相符
  • 证书在有效期内

如果期望自签证书在局域网内使用,以上三个条件都需要满足。很明显自签证书一定可以满足证书在有效期内,那么需要保证后两条。我们签发的证书必须匹配浏览器的地址栏,比如局域网的 ip 或者域名,此外还需要信任 CA。操作如下。

签发证书,加入局域网 IP 地址。

C:\>mkcert-v1.4.3-windows-amd64.exe localhost 127.0.0.1 ::1 192.168.2.25
Note: the local CA is not installed in the Java trust store.
Run "mkcert -install" for certificates to be trusted automatically ⚠️

Created a new certificate valid for the following names 📜
 - "localhost"
 - "127.0.0.1"
 - "::1"
 - "192.168.2.25"

The certificate is at "./localhost+3.pem" and the key at "./localhost+3-key.pem" ✅

It will expire on 13 November 2023 🗓

image-20210813114210800

在 mkcert 软件同目录下,生成了自签证书。如图所示。

image-20210813114343048

通过输出,我们可以看到成功生成了 localhost+3.pem​ 证书文件和 localhost+3-key.pem​ 私钥文件,只要在 web server 上使用这两个文件就可以了。

高级设置

可以使用 –help​ 查看帮助,会发现很多高级用法。

  • -cert-file FILE 、-key-file FILE 、-p12-file FILE

    可以定义输出的证书文件名

  • -client

    可以产生客户端认证证书,用于 SSL 双向认证。之前的文章介绍过使用 openssl 脚本的(Nginx SSL 快速双向认证配置 3),可以对比下

  • -pkcs12

    命令可以产生 PKCS12 格式的证书。java 程序通常不支持 PEM 格式的证书,但是支持 PKCS12 格式的证书。通过这个程序我们可以很方便的产生 PKCS12 格式的证书直接给 Java 程序使用。

# 后面还可以继续空格添加其他域名或IP地址,默认是pem格式
mkcert 127.0.0.1 localhost

# 生成p12格式的正式iis可以用,默认密码为:“changeit”
mkcert -pkcs12 192.168.10.123

# 客户端证书,默认是pem格式
mkcert -client 192.168.10.123

# 生成p12格式客户端证书,win用户可以直接导入,默认密码为:“changeit”
mkcert -pkcs12 -client 192.168.10.123
C:\>mkcert-v1.4.3-windows-amd64.exe -help
Usage of mkcert:

        $ mkcert -install
        Install the local CA in the system trust store.

        $ mkcert example.org
        Generate "example.org.pem" and "example.org-key.pem".

        $ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
        Generate "example.com+4.pem" and "example.com+4-key.pem".

        $ mkcert "*.example.it"
        Generate "_wildcard.example.it.pem" and "_wildcard.example.it-key.pem".

        $ mkcert -uninstall
        Uninstall the local CA (but do not delete it).

Advanced options:

        -cert-file FILE, -key-file FILE, -p12-file FILE
            Customize the output paths.

        -client
            Generate a certificate for client authentication.

        -ecdsa
            Generate a certificate with an ECDSA key.

        -pkcs12
            Generate a ".p12" PKCS #12 file, also know as a ".pfx" file,
            containing certificate and key for legacy applications.

        -csr CSR
            Generate a certificate based on the supplied CSR. Conflicts with
            all other flags and arguments except -install and -cert-file.

        -CAROOT
            Print the CA certificate and key storage location.

        $CAROOT (environment variable)
            Set the CA certificate and key storage location. (This allows
            maintaining multiple local CAs in parallel.)

        $TRUST_STORES (environment variable)
            A comma-separated list of trust stores to install the local
            root CA into. Options are: "system", "java" and "nss" (includes
            Firefox). Autodetected by default.
C:\>

方式二

创建脚本文件:

vim create_ssl.sh

chmod +x create_ssl.sh

复制以下脚本内容到 create_ssl.sh :

#! /bin/bash

DOMAIN=pskzs.com
## 证书适用IP
IP=$(ip addr|awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|head -n 1)
DOMAIN_EXT=$IP
DATE=3650

echo 'ip为 '$IP

rm -rf ${DOMAIN} ca.key ca.csr ca.crt

mkdir ${DOMAIN}

# 生成CA根证书
## 准备ca配置文件,得到ca.conf
cat > ${DOMAIN}/ca.conf << EOF
[ req ]
default_bits       = 4096
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = BeiJing
localityName                = Locality Name (eg, city)
localityName_default        = BeiJing
organizationName            = Organization Name (eg, company)
organizationName_default    = pskzs
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = PSKZS CA Center
EOF

## 生成ca秘钥,得到ca.key
openssl genrsa -out ca.key 4096

## 生成ca证书签发请求,得到ca.csr
openssl req -new -subj "/C=CN/ST=BeiJing/L=BeiJing/O=pskzs/CN=PSKZS CA Center" -sha256 -out ca.csr -key ca.key -config ${DOMAIN}/ca.conf

## 生成ca根证书,得到ca.crt
openssl x509 -req -days ${DATE} -in ca.csr -signkey ca.key -out ca.crt

# 生成终端用户证书
## 准备配置文件,得到server.conf
cat > ${DOMAIN}/server.conf << EOF
[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = BeiJing
localityName                = Locality Name (eg, city)
localityName_default        = BeiJing
organizationName            = Organization Name (eg, company)
organizationName_default    = pskzs
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
EOF
echo commonName_default          "=" ${DOMAIN} >> ${DOMAIN}/server.conf
cat >> ${DOMAIN}/server.conf << EOF

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
EOF
echo DNS.1 = ${DOMAIN} >> ${DOMAIN}/server.conf
echo DNS.2 = ${DOMAIN_EXT} >> ${DOMAIN}/server.conf
echo IP    = ${IP} >> ${DOMAIN}/server.conf

## 生成秘钥,得到server.key
openssl genrsa -out server.key 2048

## 生成证书签发请求,得到server.csr
openssl req -new -subj "/C=CN/ST=BeiJing/L=BeiJing/O=pskzs/CN=${DOMAIN}" -sha256 -out server.csr -key server.key -config ${DOMAIN}/server.conf

## 用CA证书生成终端用户证书,得到server.crt
openssl x509 -req -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt -extensions req_ext -extfile ${DOMAIN}/server.conf

执行脚本:

# 执行命令:./create_ssl.sh <服务器 ip>
./create_ssl.sh 192.168.0.1

生成文件如下:

[root@localhost ssl]# tree
.
├── ca.crt
├── ca.csr
├── ca.key
├── ca.srl
├── creat.sh
├── pskzs.com
│   ├── ca.conf
│   └── server.conf
├── server.crt
├── server.csr
└── server.key

1 directory, 10 files

方式三

如果系统用上方脚本出现错误时,可以尝试该脚本。(感谢 Jack Liu 大佬的开源,大家可以 Star 下,点此前往 GitHub 项目地址 。)

custom.cnf:

# [严正声明]
# 该脚本仅用于开发人员的本地Dev开发和Test测试环境测试,禁止用于其他用途!

[CNF]
# 通配符域名
DOMAIN_NAME="*.wdft.com"

# 浏览器安全策略更改(截至日期:2021-03-11):
# 1.Chrome 58版本开始的安全改变:普通名称支持被删除。使用SAN标记替代。
# 2.Chrome证书被限制为最多398天。

# 有效的398天(天数范围必须小于或等于398天)
VALID_DAYS=398

# TLS文件生成默认当前路径:
SAN_TLS_PATH="tls-ca"

# Default SUBJECT info: SUBJECT=/C=/ST=/L=/O=/OU=/CN=/emailAddress=
# C =>国家名称(2位首字母简写)
# ST =>状态名
# L =>城市名称
# O =>组织名称
# OU =>组织单位

SUBJECT.C=CN
SUBJECT.ST=Shanghai
SUBJECT.L=Shanghai
SUBJECT.O=Localhost
SUBJECT.OU=IT-DEV

gen-tlsv3-san-ca.sh:

#!/usr/bin/env bash
# Generate self-signed SAN CA Domain Name (by openssl extension v3_req)
# @author Jack Liu ljq@Github
# Description:
#   Quick self-signed CA certificates are used for local development testing.
# 
# Statement:
# this script tool from the visa book is only used to facilitate developers
# to build development and testing environment, prohibited for other purposes!
#
# Browser security policy changes(As of the date: 2021-03-11):
# 1.Security Changes in Chrome 58: Common Name Support Dropped. Using SAN instead.
# 2.Chrome certificates are limited to a maximum of 398 days.

# script version
CLI_VERSION="1.0.0"

# color sign
GREEN_COLOR="\033[32m"
CYAN_COLOR="\033[36m"
YELLOW_COLOR="\033[43;37m"
RED_COLOR="\033[31m"
GREEN_BG_COLOR="\033[47;42m"
CYAN_BG_COLOR="\033[47;46m"
RES="\033[0m"

# --------------------------- functions -----------------------------------

# etc conf
function etc_cnf(){
    item=$1
    section="CNF"
    cnf_file="./custom.cnf"
    if [ ! -f "$cnf_file" ]; then
        return 0
    fi
    cnf_options=`awk -F '=' '/'$section'/{a=1}a==1&&$1~/'${item}'/{print $2;exit}' ${cnf_file}`
    cnf_options=${cnf_options//\"/}
    echo ${cnf_options}
}

# san.conf file init
function san_cnf_init(){
    argv_domain_name=$1
    # check san conf
    SAN_CNF_FILE="san.cnf"
    if [ -f "{SAN_CNF_FILE}" ]; then
        return true
    fi

# create defautl san.cnf(Warning: EOF Monopolize a line)
cat > san.cnf << EOF
[req]
default_bits = 4096
default_md = sha256
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]

[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = ${argv_domain_name}
IP.1 = 127.0.0.1
EOF

}

# nginx vhost tpl
function nginx_vhost_tpl(){
    argv_san_tls_absolute_path=$1
    argv_host_suffix=$2

cat << EOF
server {
    listen 443;
    server_name www.${host_suffix};

    ssl on;
    # File format (.crt|.pem)
    # ssl_certificate ${argv_san_tls_absolute_path}/${argv_host_suffix}.pem;
    ssl_certificate ${argv_san_tls_absolute_path}/${argv_host_suffix}.crt;
    ssl_certificate_key ${argv_san_tls_absolute_path}/${argv_host_suffix}.key;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    keepalive_timeout 100;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    root /home/wwwroot;
}
EOF
}

# --------------------------- task exec -----------------------------------

# wildcard doamin name
DOMAIN_NAME=$(etc_cnf "DOMAIN_NAME")

# The valid max 398 days
VALID_DAYS=$(etc_cnf "VALID_DAYS")

# Serial Numbers by datetime
SET_SERIAL=$(date "+%Y%m%d%H%M%S")

# TLS files generate default current path:
SAN_TLS_PATH=$(etc_cnf "SAN_TLS_PATH")
san_tls_absolute_path=$(pwd)/${SAN_TLS_PATH}

# host_suffix
host_suffix=${DOMAIN_NAME//\*\./}

# Default SUBJECT info
subject_c=$(etc_cnf "SUBJECT.C")
subject_st=$(etc_cnf "SUBJECT.ST")
subject_l=$(etc_cnf "SUBJECT.L")
subject_o=$(etc_cnf "SUBJECT.O")
subject_ou=$(etc_cnf "SUBJECT.OU")
SUBJECT="/C=${subject_c}/ST=${subject_st}/L=${subject_l}/O=${subject_o}/OU=${subject_ou}/CN=${DOMAIN_NAME}/emailAddress=dev-test@${host_suffix}"

# help info
help_info="[usage]: [-h | -help | --help] [-v | -V | --version]"

# Current date
now_date=$(date "+%Y-%m-%d")

# help
case $1 in
    "-v"|"-V"|"--version"|"-version")
        echo -e "${CYAN_COLOR}TLS v3 SAN ca script version:${CLI_VERSION}.${RES}"
        exit
        ;;  
    "-h"|"-help"|"--help") 
        echo -e "${YELLOW_COLOR}${help_info}${RES}"
        exit
        ;;
esac

echo -e "${CYAN_BG_COLOR}------------------- [ Task is starting... ] -----------------------${RES}"

# Check openssl installation information
type openssl >/dev/null 2>&1 || { echo >&2 "OpenSSL it's not installed,Please check for installation."; exit 1; }

# san.cnf init
san_cnf_init "${DOMAIN_NAME}"

if [ ! -d "./${SAN_TLS_PATH}" ]; then
    mkdir -p ./${SAN_TLS_PATH}
    echo -e "create dir: ./${SAN_TLS_PATH}\n"
fi

# Generate ROOT CA
# Since the issuance of the certificate (no password) :
# 1.Generate the root certificate key
openssl genrsa -out ca.key 4096
# 2.Generate self-signed root certificate
openssl req -new -x509 \
    -days ${VALID_DAYS} \
    -key ca.key \
    -out ca.crt \
    -subj "$SUBJECT"

# V3 Certificate issuance
# 1.Generate Certificate Key
openssl genrsa -out server.key 4096

# 2.CSR generation using SHA256 algorithm to avoid browser weak password error
openssl req -new \
    -sha256 \
    -key server.key \
    -out server.csr \
    -subj "$SUBJECT" \
    -config san.cnf

# 3.Check CSR information
v3_csr_verify=$(openssl req -text -in server.csr | grep "X509v3 Subject Alternative Name")
if [[ "$v3_csr_verify" != "" ]] ; then
    echo -e "${GREEN_COLOR}CSR X509v3 is verified.${RES}\n"
else
    echo -e "${RED_COLOR}CSR X509v3 is not exsit. Please check that the V3 extension module is enabled.${RES}\n"
    exit
fi


# 4.Use the root certificate to sign the certificate as CSR and generate a new certificate server.crt
#   Remark: Here, the serial parameter is globally unique.
#           Certificates with the same serial value on the same device will conflict
openssl x509 -req \
    -days ${VALID_DAYS} \
    -in server.csr \
    -CA ca.crt \
    -CAkey ca.key \
    -set_serial ${SET_SERIAL} \
    -out server.crt \
    -sha256 \
    -extfile san.cnf \
    -extensions v3_req

# 5.Check to see if the CRT certificate is included
v3_crt_verify=$(openssl x509 -text -in server.crt | grep "X509v3 Subject Alternative Name")
if [[ "$v3_crt_verify" != "" ]] ; then
    echo -e "${GREEN_COLOR}CRT X509v3 is verified.${RES}\n"
else
    echo -e "${RED_COLOR}CRT X509v3 is not exsit. Please check that the v3 extension module is enabled.${RES}\n"
    exit
fi

# Copy & rename & bak & move host_suffix files
cp server.key ${host_suffix}.key
cp server.crt ${host_suffix}.crt
cp ca.crt ${host_suffix}_ca.crt
mv ${host_suffix}.key ${san_tls_absolute_path}
mv ${host_suffix}.crt ${san_tls_absolute_path}
mv ${host_suffix}_ca.crt ${san_tls_absolute_path}

# Move process files to ./dev-tls-process/[date]/
if [ ! -d "./${SAN_TLS_PATH}-process/${now_date}" ]; then
    mkdir -p "./${SAN_TLS_PATH}-process/${now_date}"
    echo -e "create dir: ./${SAN_TLS_PATH}-process/${now_date}\n"
fi
mv ca.key ./${SAN_TLS_PATH}-process/${now_date}/ca.key
mv ca.crt ./${SAN_TLS_PATH}-process/${now_date}/ca.crt
mv server.key ./${SAN_TLS_PATH}-process/${now_date}/server.key
mv server.crt ./${SAN_TLS_PATH}-process/${now_date}/server.crt
mv server.csr ./${SAN_TLS_PATH}-process/${now_date}/server.csr

# Convert .crt to .pem
openssl x509 \
    -in ${san_tls_absolute_path}/${host_suffix}.crt \
    -out ${san_tls_absolute_path}/${host_suffix}.pem \
    -outform PEM

# Nginx vhost server deploy example:
nginx_tpl_conf=$(nginx_vhost_tpl "${san_tls_absolute_path}" "${host_suffix}")

echo -e "${CYAN_BG_COLOR}----- [ Validity of Certificate info ] ---------------${RES}"
dates=$(openssl x509 -in ./${SAN_TLS_PATH}/${host_suffix}.crt -noout -dates)
dates=${dates//notBefore=/Start Datetime\: }
dates=${dates//notAfter=/Expire Datetime\: }
serial_subj=$(openssl x509 -in ./${SAN_TLS_PATH}/${host_suffix}.crt -noout -serial -subject)
echo -e "${serial_subj}\n"
echo -e "${CYAN_COLOR}${dates}${RES}\n"
echo -e "${GREEN_COLOR}The certificate generation completed !${RES}\n"

# generate nginx vhost example .conf
echo "${nginx_tpl_conf}" > ${san_tls_absolute_path}/vhost_${host_suffix}.conf

echo -e "${CYAN_BG_COLOR}----- [ Deployment instructions (Template: Nginx vhost example) ] ----${RES}\n"
echo -e "${CYAN_COLOR}${nginx_tpl_conf}${RES}\n"
echo -e "${CYAN_BG_COLOR}----- [  Client CA import install file ] ----${RES}"
echo -e "${CYAN_COLOR}[Client CA import install file]: ./${SAN_TLS_PATH}/${host_suffix}_ca.crt${RES}\n"
echo -e "${YELLOW_COLOR}The client imports the CA root certificate and sets to add trust.${RES}\n\n"

echo -e "${CYAN_BG_COLOR}------------------- [ Task is completed ] --------------------------${RES}"
exit

生成后的目录结构:

├── custom.cnf              # 脚本自定义配置文件
├── tls-ca                  # 自签证书生成目录 
│   ├── vhost_wdft.com.conf # Nginx vhost demo
│   ├── wdft.com_ca.crt     # 客户端根证书(导入或安装,添加信任)
│   ├── wdft.com.crt        # 服务器密钥对(.crt)
│   ├── wdft.com.key        # 服务器密钥对私钥(.key)
│   └── wdft.com.pem        # 服务器密钥对(.pem)
│
├── tls-ca-process         # 流程文件,用于备份和诊断
│   └── 2021-03-13
│       ├── ca.crt
│       ├── ca.key
│       ├── server.crt
│       ├── server.csr
│       └── server.key
│
├── gen-tlsv3-san-ca.sh
└── san.cnf                 # SAN: 此文件首次自动生成

配置 Nginx

将 server.crt 和 server.key 配置到 Nginx ,示例如下:

load_module /usr/lib/nginx/modules/ngx_stream_module.so;

worker_processes auto;

events {
    worker_connections  1024;
    accept_mutex on;
}

http {
    include mime.types;
    default_type application/octet-stream;
    server {
        listen 18080 ssl http2;
    
        # 证书配置
        ssl_certificate /home/ssl/server.crt;
        ssl_certificate_key /home/ssl/server.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    
        location / {
            root /home/html/;
            index index.html;
        }
    }
}

本地信任

安装 ca.crt 证书到本地电脑,操作如下:

  1. 双击 ca.crt 证书,选择安装证书

    在这里插入图片描述

  2. 将证书导入到本地计算机

    在这里插入图片描述

  3. 将证书放到 受信任的根证书颁发机构 目录下

    在这里插入图片描述

  4. 点击完成
    在这里插入图片描述

    在这里插入图片描述

测试验证

PC 安装证书完成,需要关闭 Chrome 浏览器,重新打开访问。

在这里插入图片描述

在这里插入图片描述

posted @ 2023-03-14 13:11:00 猎隼丶止戈 阅读(60) 评论(0)
发表评论
昵称
邮箱
网址