Hashicorp Vault

Vault概述

Vault是安全访问秘密的工具。一个秘密是你想要严格控制访问的任何东西,如API密钥,密码,证书等等。Vault为任何秘密提供统一的界面,同时提供严格的访问控制和记录详细的审核日志。

Hashicorp Vault解决了管理敏感信息的问题 —— 在Vault的用语中使用“secret”。在这种情况下,“管理”意味着Vault控制敏感信息的所有方面:它的生成,存储,使用以及最后它的撤销。

Hashicorp提供两种版本的Vault。本文中使用的开源版本可以免费使用,即使在商业环境中也是如此。同时还提供付费版本,其中包括不同SLA的技术支持和其他功能,例如HSM(硬件安全模块)支持。

HashiCorp Vault是一个私密信息管理工具(A tool for managing secrets),提供键值的方式保存私密信息。

秘密信息:如数据库用户名密码、ssl证书、用户敏感信息等。

特性:

1、安全的私密信息存储

2、动态的私密信息支持

3、提供对于私密信息的更新,延长有效时间的功能

4、灵活的权限控制

5、多种客户端登录验证方式

安装要求

JDK1.8+

mysql5.6

vault_1.1

redhat/centos7

openssl

安装步骤

  1. 下载安装包

最新版本:https://www.vaultproject.io/downloads.html

历史版本:https://releases.hashicorp.com/vault/

  1. 解压缩文件
  2. 生成证书
  3. 配置vault连接
  4. 启动vault
  5. 访问页面初始化/解锁/登录
  6. 开启秘钥引擎,增加测试数据验证

安装参考:

https://blog.csdn.net/zrk1000/article/details/72670037

https://blog.csdn.net/fenglongmiao/article/details/82776696

安装过程:

https://learn.hashicorp.com/vault/#getting-started

windows安装及部署Vault

openssl客户端安装

  • 下载地址:

http://slproweb.com/products/Win32OpenSSL.html

  • 软件安装与运行

直接点击安装,傻瓜式,点击下一步,知道完成即可。

将当前目录配置到windows环境变量中,以后就可以在任意位置使用openssl命令了。

打开cmd命令行测试:

openssl生成证书

生成证书

  1. 将bash压缩包解压到到valut安装目录

可以进入到bash目中查看,该目录中只有openssl.cfg配置文件

  1. 进入H:\Program Files\vault_1.1.1_windows_amd64\bash\work\ca\server目录,修改openssl.cnf配置文件,绑定域名或者ip地址。

我这里域名绑定为vault.dragon.com,如果是自定义域名,则修改在C:\Windows\System32\drivers\etc文件配置映射。

  1. cmd命令行进入到bash目录,执行create_certificates.sh 文件即可。

这里提示输入,都输入y生成证书。查看生成证书如下:

可以看到创建完成后会在work目录生成相应的证书,将根证书work/cas/root/key/cacert.crt 拷贝到本地,在浏览器中安装,并将该证书安装到本地jdk证书库。

导入自建CA的根证书

这里以Firefox为例,打开:选项 -> 隐私与安全 -> 查看证书,在证书颁发机构里面选择导入,选择文件 work/ca/root/key/cacert.crt 导入并勾选2个信任的复选框

Google: 安装及查看证书,设置-》高级-》安装证书-》双击该选项-》个人选项》导入证书即可。

360: 设置-》安全设置-》https证书管理-》个人》导入证书即可。

导入详细过程:

选择当前用户即可。

导入完成后,进入浏览器查看安装的证书详情。

注意:

1、这里安装的证书都是PKCS12类型,文件是已xxx.p12结尾证书才可以导入,如果不是该类型,则需要自行转换。

2、服务端:需要安装服务器端证书,客户端直接安装客户端认证。为了能很好的测试,我们将服务端,客户端全部安装到浏览器

安装证书到jdk库中。

1、删除原来的证书

#keytool -delete -alias vault.datu1.com -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts"

如果这里没有删除的证书,会提示找不到该证书,删除时需要输入密码,默认是changeit.

这里删除,主要是为了方式同名的冲突,证书不起作用。

注意:我这里的jdk在h盘符安装,如果盘符目录有空格,使用双引号包含路径,负责执行提示路径错误。

2、客户端导入证书

keytool -import -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts" -file work/ca/root/key/cacert.crt -alias vault.dragon.com

cmd命令进入到bash目录,导入如下:

默认密码是changeit,可以在生成证书的脚本(create_certificates.sh)中查看。

3、查看证书

keytool -list -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts"

配置nginx的ssl(备注配置nginx使用)

server {

listen       443 ssl;

server_name  server2018.cn bbs.server2018.cn server2019.cn;

ssl_certificate      work/ca/server/server_all.crt;

ssl_certificate_key  work/ca/server/privkey.pem;

ssl_session_cache    shared:SSL:1m;

ssl_session_timeout  5m;

ssl_ciphers  HIGH:!aNULL:!MD5;

ssl_prefer_server_ciphers  on;

location / {

root   html;

index  index.html index.htm;

}

}

以ssl认证启动vault服务

下载解压缩文件

下载vault_1.1.1_windows_amd64.zip压缩包后,解压缩即可。

设置环境变量

我的电脑-》右键属性-》高级系统设置-》高级-》环境变量-》系统变量-》path-》编辑环境变量-》添加vault安装目录-》确定。

通过命令行测试vault配置是否正确:

cmd命令行,执行vault查看如下,表示vault路径配置正确。

创建vault数据库及表

通过mysql客户端创建库名为vault,表名称为vault。

  • navicat客户端连接mysql:

连接-》mysql-》填写mysql连接地址、用户名、密码-》点击测试,提示连接成功即可。

  • 新建数据库:

选中新建的连接-》右键-》新建数据库-》填写库名为vault, 选择编码为UTF-8.

表不用创建,启动vault服务会自动创建。

创建ssl证书

参考《openssl证书生成》

注意:这里使用的是openssl 创建证书,通过keytool导入到jdk证书库,

并将生成的证书导入到客户端浏览器及jdk证书库,要不然浏览https访问不了。

配置vault服务启动数据库连接,ssl认证

# vault.hcl文件如下

# 开启图形界面管理

ui=true

#数据库存储

storage "mysql" {

address = "localhost:3306"

username = "root"

password = "root"

database = "vault"

table = "vault"

}

#监听地址及端口

listener "tcp" {

address = "localhost:8200"

#  tls_disable = 1

tls_cert_file = "bash/work/ca/server/server.crt"

tls_key_file = "bash/work/ca/server/privkey.pem"

tls_min_version = "tls10"

}

#api_addr = "https://localhost:8200"

启动vault服务

进入vault根据目录中,执行命令:vault server -config=ssl.hcl

以上命令启动是在控制台,不能关闭控制台,为了方便操作,使用后台进程启动,使用命令: nohup vault server -config=ssl.hcl &

控制台启动:

初始化/解锁/登录vault

以命令行初始化/解锁/登录vault

  • 初始化vault

执行命令:vault operator init -tls-skip-verify

注意:这里-tls-skip-verify表示需要以跳过认证方式初始化,由于以ssl认证启动服务,所以这里操作命令都需要认证,所有命令都增加该参数进行操作。具体追加参数位置可以通过help命令查看选项。

#注:初始化后一定要记录key和token 到固定位置文件中,后续登录及解锁都会使用。

  • 解锁

解锁命令:vault operator unseal -tls-skip-verify

注:解锁需要输入3个不同的key才可以,并且只有当Sealed 为false才可以使用,表示已经解锁

  • 登录

执行命令:vault login -tls-skip-verify -method=token  s.iSTQL6feKIFPEiJizNHEUlM2

登录ui测试:

以上表示vault安装成功,具体操作可以直接在图形界面使用。

以ui页面初始化/解锁/登录vault

vault服务启动后,如果没有在命令行进行初始化解锁,可以在ui界面访问vault服务进行初始化解锁。操作如下:

  • 启动vault服务:
  • 浏览器访问vault服务如下:

https://vault.dragon.com:8200

这里需要设置一组在紧急情况下需要使用的主钥匙。

key shsares: 表示生成key的个数,默认是5个key(必填项)。

Key threshold: 表示解锁时key的阈值,默认是3个不相同的key才能满足解锁条件(必填项)。

Encrypt output with pgp: 表示可以指定加密key的方式,可以自己编写加密规则,支持上传文件,文本直接输入。按照给定的加密顺序进行加密key. (可选的,一般不知道,使用默认加密方式)。

Encrypt root token with pgp: 表示可以指定加密token规则,可以自己编写加密规则,支持上传文件,文本直接输入(可选的,一般不知道,使用默认加密方式)。

填写完成后,点击初始化,初始化完成如下。

注意,这里需要保存生成的key,token,后续登录/解锁都需要使用,也可以直接点击《眼睛小图标》查看明文,点击download key 下载到本保存。如果忘记保存怎么办?需要将连接mysql数据库表清空,重启服务,重新进行以上操作。

json文件格式如下:

保存完成,点击解锁(continue unseal)。

将保存文件中keys_base64对应的key填写到文本框即可解锁。

将保存文件中root_token对应的token值填写到文本框即可登录。

恭喜你,以上表示对vault服务操作成功,接下来可以进行其他操作了。

开启秘钥引擎

我们这里使用kv秘钥引擎进行加密解密存储操作。

选择enable new engine

选择kv引擎,点击next.

设置版本为1.点击enable engine.

选择create secret添加秘钥。

秘钥设置完成,点击保存即可。

以上秘钥引擎设置就完成了。

启动/关闭vault服务

  • 启动:

进入到vault安装目录,执行命令 vault server –config=xxx.hcl

  • 关闭:

查看进程: netstat -ano | findstr 8200

结束进程: taskkill  /F /PID  [进程号]

例如结束进程号为123,则执行命令:taskkill  /F /PID 123

linux安装及部署Vault

openssl生成证书

生成证书

  1. 将bash压缩包解压到到valut安装目录

可以进入到bash目中查看,该目录中只有openssl.cfg配置文件

  1. 修改文件权限

chmod 755 -R bash

  1. 进入bash/work/ca/server目录,修改openssl.cnf配置文件,绑定域名或者ip地址。

我这里域名绑定为vault.dragon.com,如果是自定义域名,则修改在C:\Windows\System32\drivers\etc文件配置映射。

  1. cmd命令行进入到bash目录,执行create_certificates.sh 文件即可。

这里提示输入,都输入y生成证书。查看生成证书如下:

可以看到创建完成后会在work目录生成相应的证书,将根证书work/cas/root/key/cacert.crt 拷贝到本地,在浏览器中安装,并将该证书安装到本地jdk证书库。

导入自建CA的根证书

将linux中生成的证书下载到本地,这里以Firefox为例,打开:选项 -> 隐私与安全 -> 查看证书,在证书颁发机构里面选择导入,选择文件 work/ca/root/key/cacert.crt 导入并勾选2个信任的复选框

Google: 安装及查看证书,设置-》高级-》安装证书-》双击该选项-》个人选项》导入证书即可。

360: 设置-》安全设置-》https证书管理-》个人》导入证书即可。

安装证书到本地jdk库中。

1、删除原来的证书

#keytool -delete -alias vault.datu1.com -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts"

如果这里没有删除的证书,会提示找不到该证书,删除时需要输入密码,默认是changeit.

这里删除,主要是为了方式同名的冲突,证书不起作用。

注意:我这里的jdk在h盘符安装,如果盘符目录有空格,使用双引号包含路径,负责执行提示路径错误。

2、客户端导入证书

keytool -import -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts" -file work/ca/root/key/cacert.crt -alias vault.dragon.com

cmd命令进入到bash目录,导入如下:

默认密码是changeit,可以在生成证书的脚本(create_certificates.sh)中查看。

3、查看证书

keytool -list -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts"

以ssl认证启动vault服务

下载解压缩文件

1、下载linux安装包vault_1.1.1_linux_amd64.zip

2、上传文件到linux上解压缩。

$ unzip vault_1.1.1_linux_amd64.zip

设置环境变量

$ vim /etc/profile

#export JAVA_HOME=/usr/local/jdk1.8.0_92

export JAVA_HOME=/usr/local/jdk1.8.0_191

export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export PATH=$PATH:$JAVA_HOME/bin

#配置vault安装目录

export VAULT_HOME=/opt/vault_1.1.1_linux_amd64

export PATH=$PATH:$VAULT_HOME

$ source /etc/profile

$ echo $VAULT_HOME

创建vault数据库及表

通过mysql客户端创建库名为vault。

  • navicat客户端连接mysql:

连接-》mysql-》填写mysql连接地址、用户名、密码-》点击测试,提示连接成功即可。

  • 新建数据库:

选中新建的连接-》右键-》新建数据库-》填写库名为vault, 选择编码为UTF-8.

表不用创建,启动vault服务会自动创建。

创建ssl证书

  1. 将bash压缩包解压到到valut安装目录

可以进入到bash目中查看,该目录中只有openssl.cfg配置文件。

  1. 进入/opt/vault_1.1.1_linux_amd64/bash/work/ca/server目录,修改openssl.cnf配置文件,绑定域名或者ip地址。

我这里域名绑定为vault.vm.com,如果是自定义域名,则修改本地C:\Windows\System32\drivers\etc文件配置映射。

  1. cmd命令行进入到bash目录,执行create_certificates.sh 文件即可。

这里提示输入,都输入y生成证书。查看生成证书如下:

可以看到创建完成后会在work目录生成相应的证书,将根证书work/cas/root/key/cacert.crt 拷贝到本地,在浏览器中安装,并将该证书安装到本地jdk证书库。

注意:这里使用的是openssl 创建证书,通过keytool导入到jdk证书库,

并将生成的证书导入到客户端浏览器及jdk证书库,要不然浏览https访问不了。

配置vault服务启动数据库连接,ssl认证

# vault.hcl文件如下

# 开启图形界面管理

ui=true

#数据库存储

storage "mysql" {

address = "192.168.5.111:3306"

username = "root"

password = "12345678"

database = "vault"

table = "vault_ssl"

}

#监听地址及端口

listener "tcp" {

address = "vault.vm.com:8200"

#  tls_disable = 1

tls_cert_file = "work/ca/certs/localhost.cert.pem"

tls_key_file = "work/ca/private/localhost.decrypted.key.pem"

tls_min_version = "tls10"

max_request_duration=90

}

#api_addr = "https://172.16.102.117:8200"

启动vault服务

执行命令:vault server -config=ssl.hcl

以上命令启动是在控制台,不能关闭控制台,为了方便操作,使用后台进程启动,使用命令: nohup vault server -config=ssl.hcl &

初始完成后数据库增加如下信息:

初始化/解锁/登录vault

以命令行初始化/解锁/登录vault

查看进程: netstat -anput | grep 8200

结束进程:kill -9  进程号

  • 打开一个命令行设置变量

$ export VAULT_ADDR="http://vault.datu1.com:8200"

$ export VAULT_DEV_ROOT_TOKEN_ID="s.MlTC13p6aJuafI5jHiMZZquz "

  • 初始化vault

执行命令:vault operator init -tls-skip-verify

注意:这里-tls-skip-verify表示需要以跳过认证方式初始化,由于以ssl认证启动服务,所以这里操作命令都需要认证,所有命令都增加该参数进行操作。具体追加参数位置可以通过help命令查看选项。

#注:初始化后一定要记录key和token 到固定位置文件中,后续登录及解锁都会使用。

  • 解锁

解锁命令:vault operator unseal -tls-skip-verify

注:解锁需要输入3个不同的key才可以,并且只有当Sealed 为false才可以使用,表示已经解锁

登录ui测试:

以上表示vault安装成功,具体操作可以直接在图形界面使用。

以ui页面初始化/解锁/登录vault

vault服务启动后,如果没有在命令行进行初始化解锁,可以在ui界面访问vault服务进行初始化解锁。操作如下:

  • 启动vault服务:
  • 浏览器访问vault服务如下:

https://vault.datu1.com:8200

这里需要设置一组在紧急情况下需要使用的主钥匙。

key shsares: 表示生成key的个数,默认是5个key(必填项)。

Key threshold: 表示解锁时key的阈值,默认是3个不相同的key才能满足解锁条件(必填项)。

Encrypt output with pgp: 表示可以指定加密key的方式,可以自己编写加密规则,支持上传文件,文本直接输入。按照给定的加密顺序进行加密key. (可选的,一般不知道,使用默认加密方式)。

Encrypt root token with pgp: 表示可以指定加密token规则,可以自己编写加密规则,支持上传文件,文本直接输入(可选的,一般不知道,使用默认加密方式)。

填写完成后,点击初始化,初始化完成如下。

注意,这里需要保存生成的key,token,后续登录/解锁都需要使用,也可以直接点击《眼睛小图标》查看明文,点击download key 下载到本保存。如果忘记保存怎么办?需要将连接mysql数据库表清空,重启服务,重新进行以上操作。

json文件格式如下:

保存完成,点击解锁(continue unseal)。

将保存文件中keys_base64对应的key填写到文本框即可解锁。

将保存文件中root_token对应的token值填写到文本框即可登录。

恭喜你,以上表示对vault服务操作成功,接下来可以进行其他操作了。

开启秘钥引擎

我们这里使用kv秘钥引擎进行加密解密存储操作。

选择enable new engine

选择kv引擎,点击next.

设置版本为1.点击enable engine.

选择create secret添加秘钥。

秘钥设置完成,点击保存即可。

以上秘钥引擎设置就完成了。

启动/关闭vault服务

  • 启动:

进入到vault安装目录,执行命令 vault server –config=xxx.hcl

  • 关闭:

ps –ef | grep 8200  或者netstat –anptu | grep 8200

kill -9  [进程号]

例如结束进程号为123,则执行命令:kill -9 123

vault客户端服务部署

  1. 创建目录

[root@server95 opt]# mkdir vault_client

[root@server95 opt]# chmod 755 -R vault_client

[root@server95 opt]#

2、修改配置

修改springcloud-valut/springboot-vault.jar中vault连接配置。

注意:这里如果是以http方式连接,则scheme改为http, 如果是以https方式连接,则该scheme为https,还需要修改host连接地址及登录token 。

3、上传springcloud-valut/springboot-vault.jar 到linux中/opt/vault_client目录中

4、启动方式

直接运行springcloud-vault.jar/或者springboot-vault.jar即可。

命令航执行:java -jar springcloud-vault.jar ,这样启动时在控制台运行,不能关闭窗口,使用后台进程启动,则可以任意操作,执行命令:nohup java -jar springcloud-vault.jar &

以上表示启动成功。

5、浏览器测试

http://vault.vm.com:9090/read

Vault 命令行

https://www.vaultproject.io/docs/commands/

vault接口调用

修改配置

修改springcloud-valut/springboot-vault.jar中vault连接配置。

注意:这里如果是以http方式连接,则scheme改为http, 如果是以https方式连接,则该scheme为https,还需要修改host连接地址及登录token 。

启动方式

直接运行springcloud-vault.jar/或者springboot-vault.jar即可。

命令航执行:java -jar springcloud-vault.jar ,这样启动时在控制台运行,不能关闭窗口,使用后台进程启动,则可以任意操作,执行命令:nohup java -jar springcloud-vault.jar &

客户端提供接口服务

查询数据

接口:

http://localhost:8080/read

请求方式:

POST

参数:

path

String

请求路径

返回数据:

body

数据

status

状态(true-成功,false-失败)

msg

消息内容

结果格式如下:

{

  • body:

{

  • account: "test001",
  • id: 1,
  • name: "test001",
  • password: "test001"

},

  • footer: null,
  • total: 0,
  • status: true,
  • statusCode: "200",
  • msg: "查询秘钥成功"

}

根据key查询数据

接口:

http://localhost:8080/readByKey

请求方式:

POST

参数:

path

String

请求路径

key

String

数据名称key

返回数据:

body

数据

status

状态(true-成功,false-失败)

msg

消息内容

结果格式如下:

{

  • body: "test001",
  • footer: null,
  • total: 0,
  • status: true,
  • statusCode: "200",
  • msg: "查询秘钥成功"

}

写入数据

接口:

http://localhost:8080/write

请求方式:

POST

参数:

path

String

请求路径

必须

name

String

名称

可选

value

String

密码

可选

createTime

String

写入时间

默认写入

返回数据:

body

数据

status

状态(true-成功,false-失败)

msg

消息内容

格式如下:

{

"body": {

"id": 0,

"name": null,

"password": "1232354345645657",

"path": "kv/myapp",

"encryptKey": "encryptKey",

"createTime": "2019-04-21 14:01:18"

},

"footer": null,

"total": 0,

"status": true,

"statusCode": "200",

"msg": "保存秘钥成功"

}

删除数据

接口:

http://localhost:8080/delete

请求方式:

POST

参数:

path

String

请求路径

必须

返回数据:

body

数据

status

状态(true-成功,false-失败)

msg

消息内容

格式如下:

{

"body": null,

"footer": null,

"total": 0,

"status": true,

"statusCode": "200",

"msg": "保存秘钥成功"

}

客户端使用方式

引入前提:

  1. vault服务必须正常运行。
  2. 生成的服务端证书需要导入到本地,在本地客户端及浏览器导入证书。浏览器安装证书:

一般导出的是xx.p12或者xxx.crt文件,直接导入到浏览器即可。

  1. 以下提供四种接入都可使用,具体情况根据各自需求选择接入。

方式一:直接引入springcloud-valut/springboot-vault项目

  1. 直接将springcloud-valut/springboot-vault项目引入到自己项目依赖中。
  1. 在需要使用的地方注入VauleService接口。

该service中提供write/read/delete方法。针对于具体的公用组件,例如utils,commons等组件,提供支持httpclient方式调用springcloud-valut/springboot-vault 服务。

RestTemplate调用

@SpringBootApplication
@RestController
public class SpringbootDemoApplication {

public static void main(String[] args) {
        SpringApplication.run(SpringbootDemoApplication.class, args);
    }

@Autowired
    RestTemplate restTemplate;

@Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

@RequestMapping("/getkey")
    public void getkey() {
        String url = "http://localhost:8080/read?path=kv/myapp";
        ResponseEntity<Map> forEntity = restTemplate.getForEntity(url, Map.class);
        Map body1 = forEntity.getBody();
        System.out.println("getForEntity = " + body1);

Map var = new HashMap<>();
        ResponseEntity<Map> postForEntity = restTemplate.postForEntity(url, null, Map.class);
        Map body = postForEntity.getBody();
        System.out.println("postForEntity = " + body);

}

}

方式二:通过httpclient调用

通过httpclient调用springcloud-valut/springboot-vault服务。

请求路径:http://localhost:8080/read

请求路径详解:

https://xxxxxx:8200 表示访问连接地址。

read: 表示访问方法.

参数:

get方式提交: 直接拼接到url后即可。

post方式提交: 以表单提交。

httpclient调用方式:

1、引入jar包:

2、代码调用:

Map<String, Object> uriVariables = new HashMap<String, Object>();

// uriVariables.put("MachineTypeID", -1);

String url = "http://localhost:8080/read?path=kv/myapp";

ResponseModel responseModel = HttpRequestUtil.doGet(url, Map.class, uriVariables);

System.out.println(responseModel.getData());

String string = HttpRequestUtil.doPost(url, uriVariables);

System.out.println("string: " + string);

方式三:通过valut api调用vault服务

参考文档:

https://www.vaultproject.io/api/secret/kv/kv-v1.html

请求路径详解:

-hdeader: 表示将请求token携带在请求头中。

https://xxxxxx:8200 这个是vault服务访问连接地址。

V1: 版本号,这里我们使用v1版本.

Secret: 表示使用秘钥引擎,我们使用的是kv引擎。

my-secret:表示存储时使用的key值。

比如我们使用的是kv引擎,秘钥key是myapp. 调用连接就是:

https://127.0.0.1:8200/v1/kv/myapp

Get

$ curl \

--header "X-Vault-Token: ..." \

https://127.0.0.1:8200/v1/secret/my-secret

List

$ curl \

--header "X-Vault-Token: ..." \

--request LIST \

https://127.0.0.1:8200/v1/secret/my-secret

Create/Update

$ curl \

--header "X-Vault-Token: ..." \

--request POST \

--data {‘name’:’tom’,’password’:’1233434’} \

https://127.0.0.1:8200/v1/secret/my-secret

delete

$ curl \

--header "X-Vault-Token: ..." \

--request DELETE \

https://127.0.0.1:8200/v1/secret/my-secret

具体操作如下:

通过vault提供api操作,使用httpclient调用vault提供接口服务。

1、导入依赖包:

2、调用方法:

// get

Map map = new HashMap();

// map.put("","");//传入的参数

Map headMap = new HashMap();

headMap.put("X-Vault-Token", "s.vXLeAfFabd3bC6LgaDcnxKrv");

headMap.put("Accept", "*/*");

headMap.put("Connection", "Keep-Alive");

headMap.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");

String url2 = "https://vault.datu1.com:8200/v1/kv/myapp";

// ResponseModel res = HttpUtils.doGet(url2, headMap, map);

方式四:整合vault依赖包到自己项目中

自己引入vault相关依赖包,整合springboot/springcloud项目。

springboot项目:

  1. pom.xml文件中引入vault依赖包

<!--vault 秘钥管理依赖包-->
<dependency>
    <groupId>org.springframework.vault</groupId>
    <artifactId>spring-vault-core</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.vault</groupId>
            <artifactId>spring-vault-dependencies</artifactId>
            <version>${springboot-version}</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

  1. 在application.properties文件添加vault配置

#连接vault服务地址
vault.uri=https://vault.datu1.com:8200
#访问方式,http/https
vault.schema=https
#令牌认证
#vault.token=s.5QDK0LEm4HXdw7HDfCK7MVAu
vault.token=s.vXLeAfFabd3bC6LgaDcnxKrv
#认证方法:(默认为TOKEN,支持的认证方法是:TOKEN,APPID,APPROLE,AWS_EC2,CERT,CUBBYHOLE)
vault.authentication=TOKEN

vault.failFast=false

  1. 注入vaultTemplate配置

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractVaultConfiguration;
import java.net.URI;

/**
 *
用基于Java的bean元数据注册Spring Vault对象
 */

@Configuration
public class VaultConfig extends AbstractVaultConfiguration {

@Value("${vault.token}")
    String token;
    @Value("${vault.uri}")
    URI vaultUri;

/**
     * Specify an endpoint for connecting to Vault.
     */
   
@Override
    public VaultEndpoint vaultEndpoint() {
//        创建一个VaultEndpoint默认指向的新点https://localhost:8200。
//        return new VaultEndpoint();
        return VaultEndpoint.from(vaultUri);
    }

/**
     * Configure a client authentication.
     * Please consider a more secure authentication method
     * for production use.
     */
   
@Override
    public ClientAuthentication clientAuthentication() {
//        String property = getEnvironment().getProperty("vault.token");
        return new TokenAuthentication(token);
    }
//    @Override
//    public ClientAuthentication clientAuthentication() {
//        return new ClientCertificateAuthentication(restOperations());
//    }
//    @Bean
//    public SslConfiguration SslConfiguration() {
//        SslConfiguration sslConfiguration = SslConfiguration.forKeyStore(new FileSystemResource(keyStore), keyStorePassword);
//        return sslConfiguration;
//    }
}

4、在使用的类中注入vaultTemplate

@Autowired
private VaultTemplate vaultTemplate;

主要调用方法主要有如下:

springcloud项目:

  1. 在pom.xml中引入依赖

<!--vault 依赖包-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-vault-config</artifactId>
    <version>2.0.2.RELEASE</version>
    <!-- <scope>runtime</scope>-->
</dependency>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-vault-dependencies</artifactId>
            <version>2.0.3.RELEASE</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

  1. 在application.properties或者application.yml文件中引入vault配置

spring.cloud.vault:
    fail-fast:
true
#    uri: http://127.0.0.1:8200
    
host: vault.datu1.com
    port: 8200
    scheme: https
    token: s.vXLeAfFabd3bC6LgaDcnxKrv
    authentication: TOKEN

修改valut连接地址,token。

  1. 在自己项目中注入VaultTemplate

@Autowired
private VaultTemplate vaultTemplate;

主要调用方法主要有如下:

Keytool证书转换

crt key转p12, jks p12互转,windows生成jks

参考文档:

https://blog.csdn.net/u010801696/article/details/86546191

crt转为p12证书

openssl pkcs12 -export -in client.crt -inkey client.key -out iot.p12 -name "iot"

jks p12互转

keytool -importkeystore -srckeystore iot.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore iot.jks

keytool -importkeystore -srckeystore iot.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore iot.p12

windows生成jks

生成jks文件

keytool -genkeypair -alias icesslkey -keyalg RSA -validity 3650 -keystore icekeystore.jks

RSA是非对称密钥算法,可改为keytool其他算法,365代表证书的有效期10年

查看生成的jks文件信息

keytool -list -v -keystore icekeystore.jks

导出公钥证书

keytool -export -alias icesslkey -keystore icekeystore.jks -rfc -file icecert.cer

icecert.cer为导出的证书名字

将证书导入到truststore

keytool -import -v -trustcacerts -alias icesslkey -file icecert.cer -keystore icetruststore.ts

客户端导入证书
keytool -import -keystore "C:\Program Files\Java\jdk1.8.0_51\jre\lib\security\cacerts" -file d:\temp\cas\sg.crt -alias sgkey

将客户端cer导入证书库

keytool -import -alias cacerts -keystore cacerts -file d:\software\AKAZAM-Mail.cer

常用转换命令:

openssl pkcs12 -export -clcerts -in work/ca/server/server.crt -inkey work/ca/server/privkey.pem -out work/ca/server/server.p12

echo "[INFO] Creating  jks file with client certificate"

#生成jsk文件

keytool -importcert -keystore work/keystore.jks -file work/ca/server/server_all.crt -noprompt -storepass changeit

echo "[INFO] convertor  jks to PKCS12 "

#从JKS转换到PKCS12

keytool -importkeystore  -srckeystore work/ca/server/server.p12 -srcstoretype PKCS12 -srcstorepass changeit\

-destkeystore work/server-cert.jks -deststoretype JKS  -noprompt -storepass changeit

#同时查看多个证书详情

#openssl crl2pkcs7 -nocrl -certfile CHAINED.pem | openssl pkcs7 -print_certs -text -noout

#客户端导入证书

#keytool -import -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts" -file ca/root/key/cacert.crt -alias vault.datu1.com

#删除原来的证书

#keytool -delete -alias vault.datu1.com -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts"

#keytool -import -alias akazam_email -file akazam_email.cer -keystore cacerts

#查看证书

keytool -list -keystore cacerts

portecle证书管理工具

官网:

http://portecle.sourceforge.net/

下载地址:

https://sourceforge.net/projects/portecle/

使用教程:

https://blog.csdn.net/wyx100/article/details/46485935

安装

1、https://sourceforge.net/projects/portecle/

https://nchc.dl.sourceforge.net/project/portecle/v1.11/portecle-1.11.zip

下载直接解压缩即可。

3、进入到安装目录,命令行执行 java -jar portecle.jar  即可操作证书。

4、jdk默认证书位置H:\Program Files\Java\jdk1.8.0_92\jre\lib\security目录下cacerts文件。

5、jdk默认登录密码 changeit

导入证书参考:

https://blog.csdn.net/feng339518991/article/details/76229271

https://blog.csdn.net/kang389110772/article/details/52760460

https://blog.csdn.net/wangjunjun2008/article/details/37662851

https 异常

unable to find valid certification path to requested target

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

参考:

https://blog.csdn.net/gabriel576282253/article/details/81531746

下载证书

第一步是要下载证书

去你程序要访问的网站,点击那个锁按钮,并点击查看详情(chrome浏览器)

点击View certificate

点击详细信息

复制到文件

下一步

选择格式

生成的名称,最后保存

这里我保存在的D盘根目录下叫abc.cer

导入证书

切换到jre的/lib/security/下

执行如下命令

keytool -import -alias abc -keystore cacerts -file D://abc.cer

其中:

-alias 指定别名(推荐和证书同名)

-keystore 指定存储文件(此处固定)

-file 指定证书文件全路径(证书文件所在的目录)

注意:当切换到 cacerts 文件所在的目录时,才可指定 -keystore cacerts, 否则应该指定全路径;

此时命令行会提示你输入cacerts证书库的密码,敲入changeit即可,这是java中cacerts证书库的默认密码,当然也可自行修改。

库密钥口令输入:changeit

将会看到如下的信息

是否信任:Y

证书导入成功

查看证书,密钥仍然是changeit

keytool -list -keystore cacerts -alias vbooking

至此证书导入成功。

注意:导入证书过程中,可能会遇到一个问题,如下所示

keytool 错误: java.io.FileNotFoundException: cacerts (拒绝访问)

出现这个问题的主要原因是

WIN7下的C:\Program Files以及C:\Program Files(x86)都是只有管理员权限才能访问的目录,所有写、修改操作都会遭遇”拒绝访问”,解决方案有两种:

1.将JDK安装在D盘

2.使用管理员权限打开命令行

更新证书时,先删除原来的证书,然后导入新的证书

keytool -list -keystore cacerts

keytool -delete -alias akazam_email -keystore cacerts

keytool -import -alias akazam_email -file akazam_email.cer -keystore cacerts -trustcacerts

SSL Error: No X509TrustManager implementation available

SSL Error: No X509TrustManager implementation available

这个是由于本地jdk正式库中的证书有问题或者证书库被删除了,需要重新安装jdk恢复证书。

certificate signed by unknown authority

C:\Users\dragon>

C:\Users\dragon>vault operator init

Error initializing: Put https://127.0.0.1:8200/v1/sys/init: x509: certificate signed by unknown authority

C:\Users\dragon>

C:\Users\dragon>

原因:由于本地未导入认证证书或者使用的证书和服务器端生成的证书不一致,导致在认证过程中失败。

解决办法:将服务端生成的证书导入到浏览器,如果浏览器能正常访问,说明证书没问题,在将证书导入到本地keytool库中。

#客户端导入证书

keytool -import -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts" -file ca/root/key/cacert.crt -alias vault.datu1.com

NET::ERR_CERT_AUTHORITY_INVALID”、“ERR_CERT_COMMON_NAME_INVALID

使用Chrome访问https网站时,可能会出现以下错误,本文说明如何解决此类问题:

“您的连接不是私密连接”、“NET::ERR_CERT_AUTHORITY_INVALID”、“ERR_CERT_COMMON_NAME_INVALID”或“NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM”

解决办法:

http://sh.qihoo.com/pc/9749f0afe8716e56c?cota=4&tj_url=xz&sign=360_e39369d1&refer_scene=so_1

Status 503 secret/application: error performing token check: Vault is sealed

org.springframework.vault.VaultException: Status 503 secret/application: error performing token check: Vault is sealed

at org.springframework.vault.client.VaultResponses.buildException(VaultResponses.java:89) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.client.VaultResponses.buildException(VaultResponses.java:81) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.core.VaultTemplate.lambda$doRead$1(VaultTemplate.java:328) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.core.VaultTemplate.doWithSession(VaultTemplate.java:307) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.core.VaultTemplate.doRead(VaultTemplate.java:317) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.core.VaultTemplate.read(VaultTemplate.java:212) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.core.lease.SecretLeaseContainer.doGetSecrets(SecretLeaseContainer.java:545) [spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at

原因:由于vault服务启动后需要解锁,其他服务才可以连接,通过输入3个不同的key解锁登录即可。

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

org.springframework.vault.VaultException: Cannot initialize PropertySource for secret at secret/application; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://vault.datu1.com:8200/v1/auth/token/lookup-self": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at org.springframework.cloud.vault.config.LeasingVaultPropertySourceLocator.createVaultPropertySourceFailFast(LeasingVaultPropertySourceLocator.java:140) ~[spring-cloud-vault-config-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.cloud.vault.config.LeasingVaultPropertySourceLocator.createVaultPropertySource(LeasingVaultPropertySourceLocator.java:85) ~[spring-cloud-vault-config-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.cloud.vault.config.VaultPropertySourceLocatorSupport.doCreatePropertySources(VaultPropertySourceLocatorSupport.java:170) ~[spring-cloud-vault-config-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.cloud.vault.config.VaultPropertySourceLocatorSupport.createCompositePropertySource(VaultPropertySourceLocatorSupport.java:145) ~[spring-cloud-vault-config-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.cloud.vault.config.VaultPropertySourceLocatorSupport.locate(VaultPropertySourceLocatorSupport.java:116) ~[spring-cloud-vault-config-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:94) ~[spring-cloud-context-2.0.2.RELEASE.jar:2.0.2.RELEASE]

at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:626) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]

at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:366) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]

at org.springframework.boot.SpringApplication.run(SpringApplication.java:325) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]

at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]

at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]

at com.example.cloud.springcloudvault.SpringcloudVaultApplication.main(SpringcloudVaultApplication.java:13) [classes/:na]

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://vault.datu1.com:8200/v1/auth/token/lookup-self": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:686) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]

at org.springframework.vault.authentication.LoginTokenAdapter.lookupSelf(LoginTokenAdapter.java:95) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

at org.springframework.vault.authentication.LoginTokenAdapter.augmentWithSelfLookup(LoginTokenAdapter.java:79) ~[spring-vault-core-2.0.3.RELEASE.jar:2.0.3.RELEASE]

.............省略

... 11 common frames omitted

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.8.0_192]

at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946) ~[na:1.8.0_192]

at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316) ~[na:1.8.0_192]

at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310) ~[na:1.8.0_192]

at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639) ~[na:1.8.0_192]

at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) ~[na:1.8.0_192]

.............省略

... 37 common frames omitted

原因:1、这个问题是最麻烦的,本人测试时将服务器生成的证书导入浏览器,通过浏览器访问vault服务正常登陆,而通过客户端代码连接测试提示找不到证书。于是将证书导入jdk库中,还是提示以上问题,最后将浏览器所有自己导入的证书清空,本地jdk正式库自己导入的清空,重新将服务生成证书导入本地jdk证书库及浏览器。

2、可能还有一个原因,客户端连接服务器域名或者ip地址不对,导致访问的域名或者ip通过生成的证书进行认证时不知道你访问的这个服务提示错误。

3、可能导入的证书存在域名相同的证书,导致信息覆盖有问题。

注意:将生成的证书xx.crt 或者xx.jks导入到本地jdk安装证书库即可。

keytool -import -keystore "H:\Program Files\Java\jdk1.8.0_92\jre\lib\security\cacerts" -file ca/root/key/cacert.crt -alias vault.datu1.com

或者

keytool -import -alias cacerts -keystore cacerts -file d:\software\server.cer

vault安装及springboot,springcloud整合vault相关推荐

  1. MongoDB的学习-安装与springboot的整合

    mongoDB的学习: 1.mongodb 安装及使用 mongodb 安装及使用__mongodb安装使用 MongoDB社区下载 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上 ...

  2. Springboot/Springcloud整合ELK平台,(Filebeat方式)日志采集及管理(Elasticsearch+Logstash+Filebeat+Kibana)

    前言 最近在搞一套完整的云原生框架,详见 spring-cloud-alibaba专栏,目前已经整合的log4j2,但是想要一套可以实时观察日志的系统,就想到了ELK,然后上一篇文章是socket异步 ...

  3. springboot/springcloud整合mybatis(mysql)

    1.导入相关jar包 <!-- mysql客户端 --> <dependency><groupId>mysql</groupId><artifac ...

  4. Nginx安装配置与SpringBoot项目整合

    本篇文章将在上篇<Redis安装与SpringBoot项目整合详细教程>(上文链接:https://blog.csdn.net/sp958831205/article/details/88 ...

  5. docker 安装nacos_19.SpringCloud实战项目-SpringCloud整合Alibaba-Nacos配置中心

    SpringCloud实战项目全套学习教程连载中 PassJava 学习教程 简介 PassJava-Learning项目是PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. ...

  6. Redis 安装配置开机启动整合SpringBoot以及配置文件详解

    安装 Redis # 下载Redis wget https://download.redis.io/releases/redis-6.0.9.tar.gz# 解压 redis tar -zxvf re ...

  7. SpringBoot +SpringCloud微服务示例,整合FreeMaker,AngularJS

    SpringBoot +SpringCloud为服服务示例,整合FreeMaker,AngularJS 干货一篇,本节以SpringBoot + SpringCloud为例 构建轻量级微服务,旨在推荐 ...

  8. 尚筹网-前台-会员系统(springboot,springcloud 实战)

    总目标: 环境搭建 会员登录注册 发起众筹项目 展示众筹项目 支持众筹项目 订单 支付 1. 会员系统架构 1.1 架构图 1.2  需要创建的工程 父工程.聚合工程:shangcouwang01-m ...

  9. Spring相关文章汇总篇【Spring,SpringBoot,SpringCloud等】

      因为Spring框架包含的组件比较多,写的博客内容也比较多,虽然有分专栏但是依然不方便查找,所以专门用一篇文章来记录相关文章,会不定期更新. 一.Spring 1.基础内容 Spring介绍 Sp ...

  10. python 微服务架构实战_名师讲坛——Java微服务架构实战(SpringBoot+SpringCloud+Docker+RabbitMQ)...

    内容简介 作者简介 前言 第一部分 SpringBoot篇 第1章 SpringBoot编程起步 1.1 传统开发中痛的领悟 1.2 SpringBoot简介 1.3 SpringBoot编程起步 1 ...

最新文章

  1. Android 自定义Dialog 的使用
  2. 【计算机网络】数据链路层 : 局域网基本概念 ( 局域网分类 | 拓扑结构 | 局域网特点 | 局域网传输介质 | 介质访问控制方法 | IEEE 802 | 链路层 LLC、MAC 控制子层 )
  3. mfc中ado上传image到sql数据库
  4. git在实际开发中的应用
  5. 网络爬虫:基于对象持久化实现爬虫现场快速还原
  6. SQL Server pivot行列转换案例分析
  7. linux查找特定类型的文件中是否包含特定字段
  8. .NET Core 3.0 新 JSON API - JsonSerializer
  9. Java中dao层、service层、controller层、entity层和view层的概述
  10. 输入python出现商店_Win 10 中使用 Python 碰到的奇怪现象
  11. 想了解任务型对话机器人,我们先从自然语言理解聊起
  12. 在 Windows 上安装Rabbit MQ 指南
  13. 计算机学科 集体备课记录,信息技术学科组集体备课活动记录
  14. 万特电能表接线仿真系统 软件_电工技能——分享一款超实用的电工仿真教学接线Flash动画软件...
  15. 【快速上手教程2】疯壳·开源编队无人机-硬件资源简介
  16. Golang panic: reflect: reflect.flag.mustBeAssignable using value obtained using unexported field
  17. 极限求解--泰勒公式理解
  18. 大数据在职研究生哪个好_大数据在职研究生
  19. 统信桌面操作系统V20专业版(1021)发布:稳定又好用
  20. Spark SQL原理及常用方法详解(二)

热门文章

  1. Flutter 电子签名
  2. OPC与三菱Q系列PLC通信
  3. 11、合宙Air模块Luat开发:通过http协议获取天气信息
  4. 钉钉生成jspapi token出现IP地址不在白名单的解决办法
  5. vivox9系统基于Android,vivo X9
  6. 计算机组成原理期末知识点复习及考点总结
  7. 国内公有云对比(1.5)- 功能篇之青云
  8. oa处理会签流程图_深入剖析OA办公系统的流程管理方案
  9. “标注神器”——Zeplin使用教程(Ps版)
  10. linux usr/bin/和 usr/local/bin之间的关系,什么是软链接?