一、Fabric CA概述

图1.1 fabric-ca架构图

Fabric Server端由一个服务器集群组成,以树形架构组织CA Server节点,包含一个Root 节点和多个中间节点。每个CA要么是根CA,要么是中间CA。每个中间CA都有一个父CA,它要么是根CA,要么是另一个中间CA。

可以通过Client或SDK与服务器集群中的CA服务器进行交互。客户端首先路由到HA代理,由代理进行负载均衡,将客户端连接至某一服务器的集群成员。

包括前端的一个高可用的代理服务器,连接着若干个CA Server集群,这些集群将数据共同存放在同一个数据服务器上。数据库可能是MySQL、LDAP、PostgresSQL或者SQLite(集群环境中不推荐使用SQLite)。

集群中的所有CA服务器都共享相同的数据库,以跟踪身份和证书。如果配置了LDAP,则将标识信息保存在LDAP中而不是数据库中。

二、开始使用

(一)先决条件

1.  安装Go 1.9+

2.  设置正确的GOPATH路径,虚拟主机GOPATH:/home/greedystar/goapps

按照官方推荐的路径结构,源码会在GOPATH/src/ github.com/hyperledger/目录下

3.  安装libtool和libtdhl-dev

Ubuntu安装命令:sudo apt install libtool libltdl-dev

注意:在MacOSX上没有必要使用libtdhl-dev

(二)安装Fabric-ca

官方建议:

go get -ugithub.com/hyperledger/fabric-ca/cmd/...

注意:上面的命令将在$GOPATH/bin中安装fabric-ca-server 和fabric-ca-client二进制文件,并克隆fabric-ca源码到$GOPATH/src/github.com/hyperledger/fabric-ca/目录下,但在启动server服务时会提示错误:panic: Version is not setfor fabric-ca library,原因是fabric-ca 1.1.0版本在运行时会调用lib/metadta/version.go,其中的version变量在初始化启动时默认没有赋值,因此可以通过编译二进制文件时指定版本,命令如下:

go get -v-ldflags "-X github.com/hyperledger/fabric-ca/lib/metadata.Version=1.1.0"github.com/hyperledger/fabric-ca/cmd/...

注意:如果已经克隆了fabric-ca仓库,请确保在运行“go get”命令之前已经在主分支上了。

配置fabric-ca-server和client的命令行路径

  1. export GOPATH=/home/greedystar/apps
  2. export GOROOT=/usr/local/go
  3. export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

安装成功后可通过fabric-ca-server version查看版本如下图所示:

(三)启动服务方式

1. Docker启动

进入$GOPATH/src/github.com/hyperledger/fabric-ca/docker/server编辑docker-compose.yml,更改镜像版本为本地fabric-ca镜像版本,下图红框部分。

在docker-compose.yml文件所在目录中打开终端,执行命令:docker-compose up –d

此命令首先会拉取docker-compse.yml中配置的fabric-ca镜像,然后启动fabric-ca-server实例,由于我使用的是本地镜像,因此此命令不会去拉取镜像,只会启动ca服务器实例。

2. 原生命令启动

使用缺省设置启动fabric-ca-server,命令如下:

fabric-ca-server start -b admin:adminpw

三、Fabric CA Server

(一)初始化Server

命令:fabric-ca-server init -badmin:adminpw

-b选项提供了引导管理员的注册ID和密钥;如果配置文件中LDAP没有启用“ldap.enabled”设置,那么这是必需的(LDAP是轻量目录访问协议,英文全称是Lightweight Directory Access Protocol,是一种以树状的层次结构来存储数据的协议)

执行命令后在当前目录生成如下图所示的结构的文件。

ca-cert.pem为生成的证书文件,通过openssl命令查看证书内容,命令如下:

openssl x509 –inca-cert.pen –inform pem –noout -text

fabric-ca-config.yaml为生成的默认配置文件,如果需要自定义配置,可以使用–config xx-config.yaml来进行启动配置。也可设置FABRIC_CA_SERVER_HOME环境变量,在该环境变量所指向的目录下配置fabric-ca-server-config.yaml(默认寻找的配置文件,如无则创建默认配置文件),并在该目录下启动Server,则Server便会使用当前目录下的配置文件。

fabric-ca-server.db为存储发放证书信息的sqlite3数据库。

msp/keystore存储的即为keyfile(官方文档中所描述的ca-key.pem)

Server配置文件中可以配置一个证书签名请求(CSR),如下所示(字段的具体含义会在配置文件部分说明):

如果需要自定义CSR的属性,那么就需要自定义server配置文件,并删除掉配置文件中ca.certfile和ca.keyfile节点指向的文件,然后重新执行初始化命令。

fabric-ca-server init命令会生成一个自签名的CA证书,除非提供-u <parent-fabric-ca-server-URL> 选项。如果提供了-u选项,此服务器的CA证书将由其父Server节点进行签名。为了保证得到父节点的认证权限,<parent-fabric-ca-server-URL>的格式必须遵从<scheme>://<enrollmentID>:<secret>@<host>:<port>

如:fabric-ca-server init-u http://admin:adminpw@localhost:7054

如果想要CA Server使用个人提供的签名证书和私钥签名,则必须修改配置文件中的ca.certfile和ca.keyfile,且证书和私钥签名必须是pem格式编码的文件。

可以通过自定义CSR来生成支持ECDSA和RSA的X.509证书和密钥。以下是一个椭圆曲线数字签名算法(ECDSA)的设置,采用的曲线是prime256v1,签名算法是ecdsa-with-SHA256。

对算法和密钥长度的选择出于对安全的考量。

ECDSA提供以下选项:

size

ASN1 OID

Signature Algorithm

256

prime256v1

ecdsa-with-SHA256

384

secp384r1

ecdsa-with-SHA384

521

secp384r1

ecdsa-with-SHA521

RSA提供以下选项:

size

Modulus (bits)

Signature Algorithm

2048

2048

sha256WithRSAEncryption

4096

2096

sha512WithRSAEncryption

(二)启动Server

命令:fabric-ca-server start -b<admin>:<adminpw>

如果Fabric CA server没有被初始化,则会首先初始化Server,初始化详情请参考上一小节。

如果Fabric CA server没有启用LDAP,那么必须在命令中携带-b选项并指定至少一个引导用户。

如果想要Fabric CA server在https协议监听,那么就需要将tls.enabled设置为true。

启动成功后,Fabric CA server默认在7054端口监听(可在配置文件中配置)。

(三)配置数据库

Fabric CA默认使用SQLite数据库,这是一种嵌入式的文件数据库,如果需要将在集群中部署Fabric CA,那么就需要使用PostgreSQL或者MySQL数据库,支持的最低版本如下:

PostgreSQL: 9.5.5

MySQL: 5.7

1. PostgreSQL

下面的示例用于配置PostgreSQL数据库的链接,可以添加到Fabric CA Server的配置文件中使之生效,更具体的字段介绍可以参考https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS

  1. db:
  2. type: postgres
  3. datasource: host=localhost port=5432 user=Username password=Password dbname=fabric_ca sslmode=verify-full

sslmode字段设置了SSL认证的具体配置,如下表所示

sslmode 描述
disable 禁用SSL
require Always SSL (跳过验证)
verify-ca Always SSL (验证Server提供的证书是否由可信CA签名)
verify-full 与verify-ca相同,验证Server提供的证书是否由可信CA签名且Server的主机名与证书中的主机名匹配

如果要使用TLS,那么必须设置CA server配置文件中的db.tls属性,如果在PostgreSQL服务器中启用了SSL客户端认证,那么必须在Server配置文件中的db.tls.client字段指定客户端的证书和密钥文件,如下:

  1. db:
  2. ...
  3. tls:
  4. enabled: true
  5. certfiles:
  6. - db-server-cert.pem
  7. client:
  8. certfile: db-client-cert.pem
  9. keyfile: db-client-key.pem

certfiles:PEM编码的可信根证书文件列表

certfile 和 keyfile:PEM编码的证书和密钥文件,用来保证CA server和PostgreSQL server的安全通信。

在PostgreSQL服务器上配置SSL的基本步骤:

1. 在postgresql.conf中,取消SSLd的注释并设置为“ON”(SSL= ON)

2. 在PostgreSQL数据目录中放置证书和密钥文件。

用于生成自签名证书的指令:https://www.postgresql.org/docs/9.5/static/ssl-tcp.html

注意:自签名证书用于测试,不应用于生产环境中。

PostgreSQL服务器 - 需要客户端证书

1. 将您信任的证书颁发机构(CAS)的证书放置在PostgreSQL数据目录中的文件root.crt中

2. 在postgresql.conf中,设置“ssl_ca_file”以指向客户端的根证书(CA证书)

3. 在pg_hba.conf中的appropriate hostssl line,设置clientcert参数为1

有关在PostgreSQL服务器上配置SSL的更多细节,请参阅以下PostgreSQL文档:https://www.postgresql.org/docs/9.4/static/libpq-ssl.html

2. MySQL

下面的示例用于配置MySQL数据库的链接,可以添加到Fabric CA Server的配置文件中使之生效,更具体的字段介绍可以参考https://dev.mysql.com/doc/refman/5.7/en/identifiers.html

  1. db:
  2. type: mysql
  3. datasource: root:rootpw@tcp(localhost:3306)/fabric_ca?parseTime=true&amp;tls=custom

使用MySQL需要MySQL Server允许接受’0000-00-00’为有效的日期,需要在my.cnf中找到配置选项sql_mode,并且删除NO_ZERO_DATE,并重启服务器。

更多的使用版本配置请参考https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

如果要使用TLS,请参考上一节的配置。

在MySQL服务器上配置SSL的基本步骤

打开或创建服务器的my.cnf文件,在[mysqld] 部分增加如下代码或取消如下代码的注释。应该指向MySql服务器的密钥和证书,以及根CA证书。

[mysqld] ssl-ca=ca-cert.pem ssl-cert=server-cert.pem ssl-key=server-key.pem

可以通过以下命令查询配置是否生效:

mysql&gt; SHOW GLOBAL VARIABLES LIKE ‘have_%ssl’;

应当可以看到下表结果

variable_name Value
have_openssl YES
have_ssl YES

在MySQL服务器端SSL配置完成之后,下一步是创建一个有特权通过SSL接入MySQL服务器的用户。

mysql&gt; GRANT ALL PRIVILEGES ON . TO ‘ssluser’@’%’ IDENTIFIED BY ‘password’ REQUIRE SSL; mysql&gt; FLUSH PRIVILEGES

如果想要使用户从一个特定的IP地址访问MySQL Server,可以把“%”变为特定的IP地址。

MySQL服务器 - 需要客户端证书

安全连接的选项和用于服务器端的选项是相似的

- ssl-ca识别CA证书,如果用到,必须和服务器端用相同的证书。

- ssl-cert识别MySQL服务器的证书。

- ssl-key识别MySQL服务器的私钥。

假设你想要用一个账户来连接,这个账户没有特殊的加密要求或是被一个包括REQUIRE SSL的GRANT statement创建的,启动MySQL服务至少需要-ssl-cert和-ssl-key选项。然后在服务设置文件中设置db.tls.certfiles属性并启动CA服务。

为了要求一个客户端证书也是被指定的,创建一个用REQUIRE X509选项的账户。然后客户端也必须明确客户端密钥和证书文件;否则,MySQL server将会拒绝连接。为了给CA server指定客户端密钥和证书文件,设置db.tls.client.certfile和db.tls.client.keyfile

(四)配置LDAP

CA Server可以从LDAP Server中读取进行配置

特别地,CA Server可以连接到LDAP Server做如下事情:

- 在登记前认证身份

- 检索用于认证的身份属性

修改CA Server配置文件的LDAP部分来配置CA Server连接LDAP Server

  1. ldap:
  2. enabled: false
  3. url: &lt;scheme&gt;://&lt;adminDN&gt;:&lt;pass&gt;@&lt;host&gt;:&lt;port&gt;/&lt;base&gt;
  4. userfilter: &lt;filter&gt;
  5. attribute:
  6. names: &lt;LDAPAttrs&gt;
  7. converters:
  8. - name: &lt;fcaAttrName&gt;
  9. value: &lt;fcaExpr&gt;
  10. maps:
  11. &lt;mapName&gt;:
  12. - name: &lt;from&gt;
  13. value: &lt;to&gt;
  14. - scheme: LDAP或LDAPS中的一个。
  15. - adminDN:admin用户的名字。
  16. - pass:admin用户的密码。
  17. - host:LDAP服务器的hostname或IP地址。
  18. - port:可选的端口号,ldap默认的端口号是389,ldaps默认的端口号是636。
  19. - base:LDAP树的根,用来搜索。
  20. - filter:登录名的过滤器,例如:(uid=%s)用来搜索用用户名登陆的用户,(email=%s)用来搜索用邮箱登陆的用户。

当LDAP被配置好之后,登记过程如下:

- CA client或client SDK发送一个enrollment请求,这个请求带一个basic authorization header

- CA server接收了这个enrollment请求,对authorization header中的identity name和password进行解码,用配置文件中的“userfilter”来从identity name中查找DN(Distinquished Name),然后用identity的密码请求一个LDAP bind,如果LDAP bind成功了,enrollment过程就被授权了,可以执行了。

(五)配置多个CAs

Fabric-ca-server默认包含一个CA,可以通过cafiles 或 cacount配置选项来增加其他的CA,每一个CA都有他自己的home 目录。

1. cacount

cacount可以方便的创建多个附加CAs,他们的home directory和server directory相关,如下所示:

  1. -- &lt;Server Home&gt;
  2. |--ca
  3. |--ca1
  4. |--ca2

如下命令来启动2个附加CAs:

fabric-ca-server start -b admin:admin --cacount 2

2. cafiles

为每个要启动的CA配置CA配置文件。每个配置文件必须有唯一的CA名称和通用名称(CN),否则服务器将无法启动,因为这些名称必须是唯一的。CA配置文件将重写任何默认CA配置,CA配置文件中的任何缺失选项将由默认CA的值替换。

配置的优先级如下:

- CA Configuration file(自定义配置文件)

- Default CA CLI flags (默认命令选项)

- Default CA Environment variables(默认CA环境变量)

- Default CA Configuration file(默认配置文件)

一个CA的配置文件至少包括下述内容:

  1. ca:
  2. # Name of this CA
  3. name: &lt;CANAME&gt;
  4. csr:
  5. cn: &lt;COMMONNAME&gt;

可以设置文档结构如下:

  1. --&lt;Server Home&gt;
  2. |--ca
  3. |--ca1
  4. |-- fabric-ca-config.yaml
  5. |--ca2
  6. |-- fabric-ca-config.yaml

如下命令可以启动两个自定义配置的CA实例:

fabric-ca-server start -b admin:admin --cafiles ca/ca1/fabric-ca-config.yaml --cafiles ca/ca2/fabric-ca-config.yaml

四、Fabric CA Client

(一)登记引导身份

fabric-ca-client enroll命令用于登记身份,如下命令在本地7054端口监听的Server登记了Id为admin,密码为adminpw的引导身份(未指定-u选项即为登记引导身份)

  1. export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
  2. fabric-ca-client enroll -u http://admin:adminpw@localhost:7054

(二)注册新身份

进行注册身份请求的身份首先需要进行登录,并且拥有注册此类别身份的权限。

Fabric CA server制定了如下3种权限检验规则:

1. 注册者必须拥有hf.Registrar.Roles属性,其中的一个值与被注册身份的类型相同。例如注册User身份,则注册者的hf.Registrar.Roles属性中必须包含User值。

2. 注册者的组织关系必须与被注册身份相同或者是被注册身份组织关系的前缀。例如注册者组织关系为a.b,则被注册身份可以为a.b或a.b.*。

3. 注册者可以注册带有属性的用户,当且仅当满足如下情况:

  • 注册者可以注册以“hf”为前缀的Fabric CA保留属性,注册者拥有保留属性且取值必须是hf.Registrar.Attributes属性中的值。如果属性是类型列表,则被注册的属性的值必须等于或是注册者具有的值的子集。如果属性为布尔类型,则注册者只有在该属性值为“true”时才能注册该属性。
  • 注册非“hf”前缀的自定义属性,要求注册者拥有hf.Registrar.Attributes属性和值或属性和模式表达式。如果注册者有hf.Registrar.Attributes=ad*,那么注册者可以从身份添加或删除的属性就是以“ad”为前缀的属性。
  • 如果请求的属性名是以hf为前缀的保留属性,则会进行额外的检查,以查看该属性值是否为注册者相同属性值的子集。例如注册者的属性值为“A.B.*,X.Y.Z”,那么请求A.B.C是有效的,请求A.C.B是无效的。

下表列出了可以为身份注册的所有预置属性。注:属性的名称是区分大小写的

属性名

类型

描述

hf.Registrar.Roles

List

注册者可以管理的角色列表

hf.Registrar.DelegateRoles

List

注册者可以授予被注册身份hf.Registrar.Roles属性的角色列表

hf.Registrar.Attributes

List

注册者允许注册的属性列表

hf.GenCRL

Boolean

如果true则身份可以生成CRL

hf.Revoker

Boolean

如果true则身份可以撤销用户或证书

hf.AffiliationMgr

Boolean

如果true则身份可以管理组织关系

hf.IntermediateCA

Boolean

如果true则身份可以登记中间CA Server

注意:在注册身份时若提供属性为列表,且列表中存在重复的属性名,则以最后一个为准。

下述命令以admin身份证书注册了一个id为admin2,组织关系为org1.department1的用户,并提供了hf.Revoker的保留属性和admin的自定义属性(:exert表示该属性名和值会插入到登记证书中)

  1. export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
  2. fabric-ca-client register --id.name admin2 --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,admin=true:ecert'

可以将多个属性指定为-id.attrs选项的一部分,每个属性必须逗号分隔。对于包含逗号的属性值,属性必须封装在双引号中。见下面的例子。

  1. fabric-ca-client register -d --id.name admin2 --id.affiliation org1.department1 --id.attrs '"hf.Registrar.Roles=peer,user",hf.Revoker=true'
  2. fabric-ca-client register -d --id.name admin2 --id.affiliation org1.department1 --id.attrs '"hf.Registrar.Roles=peer,user"' --id.attrs hf.Revoker=true

可以通过修改配置文件为字段提供默认值,如下命令从命令行提供了name字段,其余字段在配置文件中读取。

  1. export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
  2. fabric-ca-client register --id.name admin3

可以通过--id.secret peerpw提供密码。

(三)登记身份

命令如下,-M选项表示填充MSP(成员服务提供商)目录结构。

  1. export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
  2. fabric-ca-client enroll -u http://peer1:peer1pw@localhost:7054 -M $FABRIC_CA_CLIENT_HOME/msp

Fabric CA Server发出的所有注册证书都有组织关系,规则如下:

1. OU层次结构的根等于身份类型。

2. 为身份标识的每个组件添加了OU。

例如,一个身份的类型为节点,它属于dept1.team1,那么它的OU层次结构为(从叶到根)OU=team1 OU=dept1 OU=peer

(四)从其他CA服务器获取CA证书链

通常,msp目录的cacerts目录必须包含CA颁发的证书链,代表节点的所有可信根证书。

fabric-ca-client getcacerts 命令即是用于从其他Fabric CA 服务器实例获取证书链。

例如,下面命令将启动另一个Fabric CA服务器,名称为CA2,在本地主机上监听7055端口,这表示区块链上的另一个可信根证书。

  1. export FABRIC_CA_SERVER_HOME=$HOME/ca2
  2. fabric-ca-server start -b admin:ca2pw -p 7055 -n CA2

下面的命令将会安装CA2的证书链到peer1的msp目录下。

  1. export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
  2. fabric-ca-client getcacert -u http://localhost:7055 -M $FABRIC_CA_CLIENT_HOME/msp

默认情况下,Fabric CA服务器以子代为先的顺序返回CA证书链,这意味着链中的每个CA证书后面跟着它的颁发者CA证书。如果需要以相反的顺序返回CA证书链,那么将环境变量CA_CHAIN_PARENT_FIRST设置为true,并重新启动FabricCA 服务器,客户端将适当地处理顺序。

(五)重新登记身份

假设证书即将过期,可以通过如下命令重新登记身份。

  1. export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
  2. fabric-ca-client reenroll

(六)撤销证书或身份

为了撤销证书或身份,调用身份必须具有hf.Revoker和hf.Registrar.Roles属性。调用身份只能撤销证书或与调用身份组织关系相同和匹配前缀的身份。此外,撤消者只能撤销在撤消者的hf.Registrar.Roles角色属性中列出的类型的身份。

下面的命令禁用身份并撤销与该身份相关联的所有证书。Fabric CA Server接收到的所有该身份的请求都将被拒绝。

fabric-ca-client revoke -e &lt;enrollment_id&gt; -r &lt;reason&gt;

reason 选项的具体取值请参考:

http://hyperledger-fabric-ca.readthedocs.io/en/release-1.1/users-guide.html#reenrolling-an-identity

fabric-ca-clientrevoke -e peer1 –gencrl

-gencrl会生成CRL并存储在<msp folder>/crls/crl.pem

(七)通过命令生成CRL

任何拥有hf.GenCRL属性的身份都可以创建一个CRL,该CRL包含在某一段期间被撤销的所有证书的序列号。创建的CRL存储在<msp文件夹> /crl/crl.pem文件中。

  1. export FABRIC_CA_CLIENT_HOME=~/clientconfig
  2. fabric-ca-client gencrl -M ~/msp

上述命令将创建包含所有被撤销的证书(过期和未过期)的CRL,并将CRL存储在~/msp/crl/crl.pem文件中。

  1. export FABRIC_CA_CLIENT_HOME=~/clientconfig
  2. fabric-ca-client gencrl --caname "" --revokedafter 2017-09-13T16:39:57-08:00 --revokedbefore 2017-09-21T16:39:57-08:00 -M ~/msp

上述命令将创建一个CRL,包含所有在2017-09-13T16:39:57-08:00之后撤销的(由–revokedafter指定)和2017-09-21T16:39:57-08:00之前撤销的(由-revokedbefore指定)的证书(过期和未过期),并将CRL存储在~/msp/crl/crl.pem中。

-caname标志表示生成CRL请求发送到的CA名字,此命令会将请求发送至默认CA。

  1. export FABRIC_CA_CLIENT_HOME=~/clientconfig
  2. fabric-ca-client gencrl --expireafter 2017-09-13T16:39:57-08:00 --expirebefore 2018-09-13T16:39:57-08:00 --revokedafter 2017-09-13T16:39:57-08:00 --revokedbefore 2017-09-21T16:39:57-08:00 -M ~/msp

gencrl命令还接受-expireafter和-expirebefore选项,用于为撤销的证书指定超时时间范围,如上述命令所示。

(八)基于属性的访问控制

访问控制决策可以由基于身份属性的链码(和由Hyperledger Fabric运行时)来实现,称为基于属性的访问控制,简称ABAC。

为了使这成为可能,身份的注册证书(ECert)可以包含一个或多个属性名称和值。然后链码提取属性值来进行访问控制决策。

有两种方法获得具有属性的注册证书:

1. 注册身份时,可以指定为身份颁发的注册证书应默认包含的属性。此行为可以在注册时重写,但这对于建立默认行为非常有用,如果注册发生在您的应用程序之外,则不需要任何应用程序更改。

当用户在注册时没有明确地请求属性时,“:ecert”后缀会导致app1Admin属性默认插入user的注册证书中。

fabric-ca-client register --id.name user1 --id.secret user1pw --id.type user --id.affiliation org1 --id.attrs 'app1Admin=true:ecert,email=user1@gmail.com'

2. 登记身份时,可以显式请求将一个或多个属性添加到证书中。对于所请求的每个属性,可以指定属性是否是可选的。如果不需要请求,并且身份不具有属性,则会发生错误。

如在命令中指定了address,但身份中不具有该属性则会报错。

fabric-ca-client enroll -u http://user1:user1pw@localhost:7054 --enrollment.attrs "email,phone:opt"

下表显示了每个身份自动注册的三个属性

属性名

属性值

hf.EnrollmentID

The enrollment ID of the identity

hf.Type

The type of the identity

hf.Affiliation

The affiliation of the identity

若要将任何上述属性默认添加到证书中,必须显式地使用“:ecert”注册属性,如下命令所示:

fabric-ca-clientregister --id.name user1 --id.secret user1pw --id.type user --id.affiliationorg1 --id.attrs 'hf.Affiliation=org1:ecert'

(九)动态服务器配置更新

动态对CA Server进行配置更新,无需重启Server。本节中的所有命令都要求首先通过执行fabric-ca-client enroll命令进行登记。

1. 使用fabric-ca-client命令动态更新身份

如果客户端身份不满足以下所有情况,则会发生授权失败:

(1)客户端身份必须具有“hf.Registrar.Roles”属性,该属性值是具有逗号分隔的列表,其中一个属性值与被更新的身份类型相同。例如,如果Client身份的“hf.Registrar.Roles”属性取值为“client,peer”,则Client可以更新client和peer类型的身份,而不能更新orderer。

(2)客户端身份的归属关系必须等同或匹配被更新身份的归属关系前缀。例如,客户端归属于a.b,则其可以更新归属于a.b.c的身份,但不能更新归属于a.c的身份。如果一个身份需要根关联,那么更新请求应该指定“.”用于关联,并且客户端也必须具有根关联。

2. 获取身份信息

  1. fabric-ca-client identity list --id user1
  2. fabric-ca-client identity list

3. 添加身份

有两种方法添加身份,如下所示:

  1. fabric-ca-client identity add user1 --json '{"secret": "user1pw", "type": "user", "affiliation": "org1", "max_enrollments": 1, "attrs": [{"name": "hf.Revoker", "value": "true"}]}'
  2. fabric-ca-client identity add user1 --secret user1pw --type user --affiliation . --maxenrollments 1 --attrs hf.Revoker=true

下表列出了身份的所有字段以及它们是否是必需的或可选的,以及它们可能具有的任何默认值。

Fields

Required

Default Value

ID

Yes

Secret

No

Affiliation

No

Caller’s Affiliation

Type

No

client

Maxenrollments

No

0

Attributes

No

4. 修改身份

有两种方法可以用来修改身份信息,一种是通过json字符串,另一种是直接使用选项标识。

如下命令通过json对user1的多个信息进行了修改:

fabric-ca-client identity modify user1 --json '{"secret": "newPassword", "affiliation": ".", "attrs": [{"name": "hf.Regisrar.Roles", "value": "peer,client"},{"name": "hf.Revoker", "value": "true"}]}'

如下命令直接使用选项标识修改身份信息:

  1. fabric-ca-client identity modify user1 --secret newsecret
  2. fabric-ca-client identity modify user1 --affiliation org2
  3. fabric-ca-client identity modify user1 --type peer
  4. fabric-ca-client identity modify user1 --maxenrollments -2 // -2表示使用CA的最大登记设置
  5. fabric-ca-client identity modify user1 --secret newpass --type peer

5. 移除身份

下面命令删除身份user1,并撤消与user1身份相关联的任何证书。

fabric-ca-client identity remove user1

注意:在默认情况下,Fabric CA服务器是禁用身份的删除的,但可以通过设置–cfg.identities.allowremove选项启动Fabric CA服务器启用。

6. 添加组织关系

要求client满足:

(1)client身份必须拥有hf.AffiliationMgr属性,且取值为true

(2)client身份的归属关系必须在被更新的层次之上,如client归属于a.b,则client可添加a.b.*归属关系

命令 : fabric-ca-client affiliation add org1.dept1

7. 修改组织关系

要求client满足:

(1)client身份必须拥有hf.AffiliationMgr属性,且取值为true

(2)client身份的归属关系必须在被更新的层次之上

(3)如果修改的组织关系需要级联修改身份信息,那么client身份必须拥有修改身份信息的权限

如下命令将org2的名字修改为org3,若需要级联修改身份信息,则会报错

fabric-ca-client affiliation modify org2 --name org3

添加—force选项即可级联修改身份信息

fabric-ca-client affiliation modify org1 --name org2 --force

8. 移除组织关系

要求client满足:参考7.修改组织关系

如下命令将会移除org2,同时移除其子组织关系,但若存在需要级联移除的身份,则会报错

fabric-ca-client affiliation remove org2

添加—force选项即可级联删除身份信息

fabric-ca-client affiliation remove org2 --force

注意:在默认情况下,Fabric CA服务器是禁用身份的删除的,但可以通过设置–cfg. affiliations.allowremove选项启动FabricCA服务器启用。

9. 列举组织关系信息

要求client满足:参考6.添加组织关系,如下命令列出特定组织关系的信息

fabric-ca-client affiliation list --affiliation org2.dept1

如下命令列出全部组织关系的信息,但需要具有相应的权限

fabric-ca-client affiliation list

(十)指定特定的CA实例

当服务器运行多个CA实例时,请求可以指向特定的CA。默认情况下,如果在客户端请求中没有指定CA名称,则请求将指向服务器上的默认CA。可以在客户端命令的命令行上指定CA名称,如下所示:

fabric-ca-client enroll -u http://admin:adminpw@localhost:7054 --caname &lt;caname&gt;

(十一)启动中间CA

为了创建中间CA的签名证书,中间CA必须以与fabric-ca-client相同的方式向一个父CA进行登记。通过使用-U选项来指定父CA的URL、登记ID和密码。此中间CA必须具有hf.IntermediateCA属性且取值为true。待颁发证书的CN会设置为注册的ID。如果中间CA试图显式指定CN值,则会发生错误。

fabric-ca-server start -b admin:adminpw -u http://&lt;enrollmentID&gt;:&lt;secret&gt;@&lt;parentserver&gt;:&lt;parentport&gt;

五、证书格式

通过openssl命令查看证书内容

openssl x509 –inca-cert.pen –inform pem –noout –text

数字认证证书是记录了一个群体一系列属性的证件。最常见的数字认证证书是遵守X.509标准的证书。X.509标准允许将群体的身份详细信息编码。

下图的数字认证证书是一个SUBJECT由(C=US, ST=NorthCarolina, O=Hyperledger, OU=Fabric, CN=fabric-ca-server)的属性构成。fabric-ca-server(注册的身份的名称,无实际意义,下称该身份)的证书就是他的身份证,提供了能证明该身份是他自己的关键事实。

一个数字认证证书描绘了该身份,该身份是这个证书对应的subject。这个数字认证证书也包括了许多其他的信息,该身份的公钥在他的数字认证证书中,而私钥却不在里面(私钥必须保密)。

该身份的所有属性特征都可以通过数学加密的方式记录,所以篡改证书信息会使证书无效。该身份可以携带他的证书来证明他的身份,只要其它群体信任向该身份颁发证书的机构(CA)。只要CA确保了私有信息的安全,就可以确保该身份的证书没有被篡改。

六、Fabric-CA-Client配置文件

  1. #############################################################################
  2. # fabric-ca-client 命令配置文件.
  3. #############################################################################
  4. # URL of the Fabric-ca-server (default: http://localhost:7054)
  5. url: http://localhost:7054
  6. # Membership Service Provider (MSP) 目录
  7. # 配置MSP目录在客户端用户登记peer或drderer的时候很有用,这可以使得登记结构以
  8. # MSP所期望的格式存储
  9. mspdir: msp
  10. #############################################################################
  11. # TLS(安全传输层协议)部分 用于保证socket连接的安全
  12. # certfiles - PEM-编码的可信任的根证书文件列表
  13. # client:
  14. # certfile - PEM-编码的证书文件(需提供:当服务器启动了对客户端的身份验证)
  15. # keyfile - PEM-编码的私钥文件(需提供:当服务器启动了对客户端的身份验证)
  16. #############################################################################
  17. tls:
  18. certfiles:
  19. client:
  20. certfile:
  21. keyfile:
  22. #############################################################################
  23. # CSR部分,用于为登记证书编码生成证书签名请求
  24. #
  25. # cn – 用于CAs决定为谁生成证书
  26. # serialnumber – 序列号属性,将作为证书的一部分。例如,某一公司拥有证书颁发机构,其希# 望将员工的工号包含在证书中。
  27. # 注意:这里的serialnumber与Server配置的serialnumber不一样,此处序列号将作为证书# 的一部分
  28. # names - name对象列表,每个name对象都至少包含"C", "L", "O", "ST"中的一个值(或者# 任意组合)
  29. # "C": 国家
  30. # "L": 地区或直辖市(如城市或城镇名称)
  31. # "O": 组织
  32. # "OU": 组织单位(如拥有密钥的部门),也可以用来作为DBS的名称。
  33. # "ST": 州或省
  34. # 注意:OU或OUs是根据身份类型和所属组织关系来设置的,Ous根据如下规则计算登录
  35. # OU=&lt;type&gt;, OU=&lt;affiliationRoot&gt;, ...,OU=&lt;affiliationLeaf&gt;
  36. # 例如:从属于org1.dept2.team3的client进行登录,则Ous为:OU=client, OU=org1,
  37. # OU=dept2, OU=team3
  38. # hosts – 该证书有效的主机名列表
  39. #############################################################################
  40. csr:
  41. cn: admin
  42. serialnumber:
  43. names:
  44. - C: US
  45. ST: North Carolina
  46. L:
  47. O: Hyperledger
  48. OU: Fabric
  49. hosts:
  50. - home
  51. #############################################################################
  52. # id部分用于向fabric-ca-server注册一个新的身份
  53. #
  54. # name – 身份的唯一名称
  55. # type – 注册的身份类型 (e.g. 'peer, app, user')
  56. # affiliation – 身份的组织关系
  57. # maxenrollments –secret(??密码??)可以用来登记的最大次数
  58. # -1:无限制 0:使用CA的最大登记值
  59. # attributes – 身份的name/value 属性列表
  60. #############################################################################
  61. id:
  62. name:
  63. type:
  64. affiliation:
  65. maxenrollments: 0
  66. attributes:
  67. # - name:
  68. # value:
  69. #############################################################################
  70. # enrollment部分用于向fabric-ca server登记一个身份
  71. # profile -颁发证书时使用的签名配置文件的名称
  72. # label -在HSM(高速存储器)操作中使用的标签
  73. #############################################################################
  74. enrollment:
  75. profile:
  76. label:
  77. #############################################################################
  78. # 要连接的fabric-ca-server名
  79. #############################################################################
  80. caname:
  81. #############################################################################
  82. # BCCSP (BlockChain Crypto Service Provider) 部分允许选择使用的加密实现库
  83. #############################################################################
  84. bccsp:
  85. default: SW
  86. sw:
  87. hash: SHA2
  88. security: 256
  89. filekeystore:
  90. # 存储密钥的目录
  91. keystore: msp/keystore

七、Fabric-CA-Server配置文件

  1. #############################################################################
  2. # fabric-ca-server命令配置文件
  3. #############################################################################
  4. # 配置文件版本
  5. version: 1.1.0
  6. # 服务器监听端口 (default: 7054)
  7. port: 7054
  8. # 开启调试日志 (default: false)
  9. debug: false
  10. # 证书吊销列表大小限制,单位:字节(default: 512000)
  11. crlsizelimit: 512000
  12. #############################################################################
  13. # Server监听端口的安全传输层协议(TLS)
  14. # type - 客户端认证支持如下类型:NoClientCert, RequestClientCert,
  15. # RequireAnyClientCert, VerifyClientCertIfGiven, RequireAndVerifyClientCert.
  16. # certfiles – 根证书列表,用于Server验证Client证书
  17. #############################################################################
  18. tls:
  19. # 启用TLS (default: false)
  20. enabled: false
  21. certfile:
  22. keyfile:
  23. clientauth:
  24. type: noclientcert
  25. certfiles:
  26. #############################################################################
  27. # CA部分包含与CA相关的信息
  28. # name – CA在区块链网络中唯一的名称
  29. # keyfile – 密钥文件,只用于将私钥导入BCCSP
  30. # certfile – 证书文件
  31. # keyfile和certfile用于办法注册证书(ECert)和交易证书(TCert)
  32. # chainfile - (如果存在)包含被此CA信任的证书链,通常链中第一个证书为root CA的证书
  33. ##############################################################################
  34. ca:
  35. name:
  36. keyfile:
  37. certfile:
  38. chainfile:
  39. #############################################################################
  40. # 指定生成的CRL的到期时间,将此属性指定的小时数添加到UTC时间,结果时间用于设置CRL
  41. # 的下一个更新日期。
  42. #############################################################################
  43. crl:
  44. expiry: 24h
  45. #############################################################################
  46. # registry部分控制着Server如何做以下两件事:
  47. # 1) 包含username和password(也叫作enrollment ID 和 secret)的登记验证请求
  48. # 2) 一旦经过身份验证,就可以检索出身份的name/value 属性对,Server可将属性对随机
  49. # 加入到用于区块链交易问题的交易证书(Tcerts)中,这些属性对于在chaincode中进行
  50. # 访问控制决策非常有用。
  51. # 两个主要的配置选项:
  52. # 1) fabric-ca-server作为登记处.
  53. # 如果ldap部分的ldap.enabled为false,则fabric-ca-server作为登记处
  54. # 2) LDAP server作为登记处
  55. # 如果ldap部分的ldap.enabled为true,则LDAP server作为登记处,也就是说registry
  56. # 部分被忽略
  57. # 在这种情况下,fabric-ca-server调用LDAP服务器来执行登记任务
  58. #############################################################################
  59. registry:
  60. # password/secret 可以重复使用进行登记的次数,默认:-1,即无限制
  61. maxenrollments: -1
  62. # 包含身份信息
  63. identities:
  64. - name: admin
  65. pass: admin
  66. type: client
  67. affiliation: ""
  68. attrs:
  69. hf.Registrar.Roles: "peer,orderer,client,user"
  70. hf.Registrar.DelegateRoles: "peer,orderer,client,user"
  71. hf.Revoker: true
  72. hf.IntermediateCA: true
  73. hf.GenCRL: true
  74. hf.Registrar.Attributes: "*"
  75. hf.AffiliationMgr: true
  76. #############################################################################
  77. # Database section
  78. # 支持数据库: "sqlite3", "postgres", and "mysql".
  79. # 数据源的取值依赖于数据库类型
  80. # 如果是"sqlite3",则数据源取值为用户数据库存储的文件名,由于"sqlite3"是一个嵌入
  81. # 式的数据库,因此如果想在集群服务器上运行fabric-ca-server,那么必须选择"postgres"
  82. # 或"mysql"
  83. #############################################################################
  84. db:
  85. type: sqlite3
  86. datasource: fabric-ca-server.db
  87. tls:
  88. enabled: false
  89. certfiles:
  90. client:
  91. certfile:
  92. keyfile:
  93. #############################################################################
  94. # LDAP section
  95. # 如果开启LDAP,那么fabric-ca-server将调用LDAP处理:
  96. # 1) 为登记请求认证enrollmentID and secret (username and password)
  97. # 2) 获取身份属性
  98. #############################################################################
  99. ldap:
  100. # 如果启用, 那么registry 部分将会被忽略. (default: false)
  101. enabled: false
  102. # The URL of the LDAP server
  103. url: ldap://&lt;adminDN&gt;:&lt;adminPassword&gt;@&lt;host&gt;:&lt;port&gt;/&lt;base&gt;
  104. # 客户端连接LDAP server的TLS 配置
  105. tls:
  106. certfiles:
  107. client:
  108. certfile:
  109. keyfile:
  110. # 属性相关的配置,从LDAP条目映射到Fabric CA属性。
  111. attribute:
  112. # 'names'是一个字符串数组,包含从LDAP服务器请求的LDAP身份条目的LDAP属性名
  113. names: ['uid','member']
  114. # 'converters' 用于将LDAP条目转换为fabric CA 属性
  115. # 如下将表达式&lt; attr("uid") =~ "revoker*"&gt;( LDAP的uid属性是否由'revoker'开头) 的值转换为fabric CA属性"hf.Revoker"
  116. # converters:
  117. # - name: hf.Revoker
  118. # value: attr("uid") =~ "revoker*"
  119. converters:
  120. - name:
  121. value:
  122. # The 'maps' 用于在'converters'中对属性进行映射
  123. # 假设属性'member'的值为'dn1', 'dn2', and 'dn3'. 对于如下配置
  124. # converters:
  125. # - name: hf.Registrar.Roles
  126. # value: map(attr("member"),"groups")
  127. # maps:
  128. # groups:
  129. # - name: dn1
  130. # value: peer
  131. # - name: dn2
  132. # value: client
  133. # 用户的'hf.Registrar.Roles'取值将为"peer,client,dn3".
  134. # 因为maps中将dn1,dn2分别映射为peer、client
  135. maps:
  136. groups:
  137. - name:
  138. value:
  139. #############################################################################
  140. # Affiliations section. Fabric CA Server可以使用本节指定的从属关系进行引导
  141. # 从属关系本质上是分层的,例如:
  142. # businessunit1:
  143. # department1:
  144. # - team1
  145. # businessunit2:
  146. # - department2
  147. # - department3
  148. # 注意:从属关系是区分大小写的,除了Server配置文件中指定的非叶子从属关系,它们总是
  149. # 存储在小写的情况下(即在Server配置文件中配置的从属关系中,叶子结点区分大小写,而
  150. # 非叶子节点自动按小写存储)
  151. #############################################################################
  152. affiliations:
  153. org1:
  154. - department1
  155. - department2
  156. org2:
  157. - department1
  158. #############################################################################
  159. # Signing section 签名部分
  160. #
  161. # default部分用于签发登记证书,expiry默认为8760h(1年)
  162. #
  163. # profile.ca用于签发中间CA证书,ca.expiry默认43800h(5年)
  164. # 注意:
  165. # isca为true意味着它会颁发CA证书.
  166. # maxpathlen为0 表示中间CA不能发布其他中间CA证书,尽管它仍然可以发布最终实
  167. # 体证书
  168. #
  169. # tls 用于签署TLS证书请求
  170. # expiry 默认8760h(1年)
  171. ##############################################################################
  172. signing:
  173. default:
  174. usage:
  175. - digital signature
  176. expiry: 8760h
  177. profiles:
  178. ca:
  179. usage:
  180. - cert sign
  181. - crl sign
  182. expiry: 43800h
  183. caconstraint:
  184. isca: true
  185. maxpathlen: 0
  186. tls:
  187. usage:
  188. - signing
  189. - key encipherment
  190. - server auth
  191. - client auth
  192. - key agreement
  193. expiry: 8760h
  194. ###########################################################################
  195. # 证书签名请求(CSR)部分, 控制根CA证书的创建
  196. #
  197. # 根CA证书的到期时间配置为ca.expiry字段,默认值为“131400小时(15年)
  198. #
  199. # ca.pathlength字段用于限制CA证书层次结构
  200. # 1)无pathlength值意味着不要求限制。
  201. # 2)pathlength:1(根CA的默认值)意味着根CA可以发布中间CA证书,但是这些中间
  202. # CAs可能不会依次发布其他CA证书,尽管它们仍然可以发布最终实体证书。
  203. # 3)pathlength:0(中间CA的默认值)意味着它不能发布CA证书,尽管它仍然可以发布
  204. # 最终实体证书。
  205. ############################################################################
  206. csr:
  207. cn: fabric-ca-server
  208. names:
  209. - C: US
  210. ST: "North Carolina"
  211. L:
  212. O: Hyperledger
  213. OU: Fabric
  214. hosts:
  215. - home
  216. - localhost
  217. ca:
  218. expiry: 131400h
  219. pathlength: 1
  220. #############################################################################
  221. # BCCSP (BlockChain Crypto Service Provider) 部分允许选择使用的加密实现库
  222. #############################################################################
  223. bccsp:
  224. default: SW
  225. sw:
  226. hash: SHA2
  227. security: 256
  228. filekeystore:
  229. # 存储密钥的目录
  230. keystore: msp/keystore
  231. #############################################################################
  232. # Multi CA section
  233. #
  234. # 每个Fabric CA server 默认包含一个CA,这一部分用于在一个Server上设置多个CA
  235. #
  236. # 1) --cacount &lt;number-of-CAs&gt;
  237. # 自动生成&lt;number-of-CAs&gt;个非默认的CA,自动命名"ca1", "ca2", ... "caN",通常
  238. # 用于开发环境快速创建多个CA
  239. # 2) --cafiles &lt;CA-config-files&gt;
  240. # 对于列表中的每个CA配置文件,生成一个单独的签名CA。该列表中的每个CA配置文件可
  241. # 以包含与服务器配置文件中除了端口、调试和TLS部分中所有元素相同的元素
  242. # 示例:
  243. # fabric-ca-server start -b admin:adminpw --cacount 2
  244. # fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-
  245. # config.yaml --cafiles ca/ca2/fabric-ca-server-config.yaml
  246. #############################################################################
  247. cacount:
  248. cafiles:
  249. #############################################################################
  250. # Intermediate CA section
  251. #
  252. # 服务器和CAs之间的关系如下:
  253. # 1)单个服务器进程可以包含或充当一个或多个CAS,这是由上面的Multi CA部分配置的
  254. # 2)每个CA是根CA或中间CA
  255. # 3)每个中间CA有一个父CA,它是根CA或另一个中间CA
  256. #
  257. # 如果设置了parentserver.url属性,则这是一个带有指定父CA的中间CA
  258. # parentserver section
  259. # url -父Server的URL
  260. # caname – 父CA在服务器内注册的名称
  261. #
  262. # enrollment section 用于通过父CA登记中间CA
  263. # profile -在颁发证书时使用的签名配置文件的名称
  264. # label -用于HSM操作的标签
  265. #
  266. # tls section (安全传输层协议)部分 用于保证socket连接的安全
  267. # certfiles - PEM-编码的可信任的根证书文件列表
  268. # client:
  269. # certfile - PEM-编码的证书文件(需提供:当服务器启动了对客户端的身份验证)
  270. # keyfile - PEM-编码的私钥文件(需提供:当服务器启动了对客户端的身份验证)
  271. #############################################################################
  272. intermediate:
  273. parentserver:
  274. url:
  275. caname:
  276. enrollment:
  277. hosts:
  278. profile:
  279. label:
  280. tls:
  281. certfiles:
  282. client:
  283. certfile:
  284. keyfile:

原文链接:Fabric CA User's Guide

欢迎大家交流沟通

Fabric CA 官方用户指南相关推荐

  1. Fabric CA官方文档翻译——Planning for a CA

    原文https://hyperledger-fabric-ca.readthedocs.io/en/latest/deployguide/ca-deploy-topology.html 读者:架构师, ...

  2. Java架构师之旅(二十九 附录《MyBatis3 用户指南》中文版)

    夜光序言: 岁月波光粼粼,赋予爱与生命,唯有生活不能被他人代替,只会有寂寞相随~~ 正文: MyBatis 3 2010.08.01  翻译的一个版本,虽难比较老了,但是有一些基础还是值得学习,毕竟是 ...

  3. Android官方技术文档翻译——Gradle 插件用户指南(5)

    昨晚把第五章未译完的几句话攻克了.只是第六章没怎么译,明后天又是周末,假设周一前第六章翻译完的话,周一再发第六章. 本文译自Android官方技术文档<Gradle Plugin User Gu ...

  4. Fabric CA国密版本的一种替代方案--使用cryptogen工具增加新用户

    在Fabric超级账本中,如果我们想动态增加用户发行证书,一般会使用Fabric CA或者其它CA.然而在国密改造场景中,当前缺乏可用的开源的Fabric CA国密版本.因此,笔者研究了一下,发现了一 ...

  5. Fabric CA/数字证书管理

    MSP(Membership Service Provider)成员管理服务提供商 名词: 1.CSR(Cerificate Signing Request):证书签署请求文件 CSR里包含申请者的 ...

  6. Hyperledger Fabric 1.0 快速搭建 -------- 多机部署 Fabric CA节点服务

    前言 在这里我推荐两位大神的博客,可以参考或者直接跟着这两位大神学习,我是阅读这两位大神的博客和<深度探索区块链Hyperledger技术与应用>一书部署的 <深度探索区块链Hype ...

  7. Python包装用户指南(删减了讨论和新闻部分)

    Python包装用户指南 欢迎使用Python Packaging用户指南,这是一系列教程和参考资料,可帮助您使用现代工具分发和安装Python包. 本指南由Python Packaging Auth ...

  8. 新书上市 | 流行SQL引擎Presto,官方实战指南来了

    2012年,Facebook的用户数量突破10亿,成为当时全球最大的社交网络.也是在这一年,Facebook的Hive数据仓库达到了250PB,每天需要处理成千上万条查询.在Facebook内部,Hi ...

  9. Quartz.net官方开发指南 第十课: 配置、资源使用以及SchedulerFactory

    Quartz以模块方式构架,因此,要使它运行,几个组件必须很好的咬合在一起.幸运的是,已经有了一些现存的助手可以完成这些工作. 在Quartz进行工作之前需要被配置的组件主要有: • ThreadPo ...

最新文章

  1. 当程序出Bug时,程序员最喜欢说的30句话
  2. 关于稳定性和故障的一点思考,每个互联网公司都吃过这个亏!
  3. 使用Redis实现最近N条数据的决策
  4. Python语言学习:创建/删除文件/文件夹、获取当前文件/文件夹路径(系统环境路径/目录)、获取当前文件夹下的所有子文件路径等代码(os系列用法)实现之详细攻略
  5. 如何优化电子邮件营销的效果
  6. python中表示单一数据的类型被称为_各种Python数据类型的完整列表
  7. 作者:马晓磊(1985-),男,北京航空航天大学交通科学与工程学院交通运输工程系副教授、博士生导师。...
  8. 深入理解JavaScript系列:闭包(Closures)
  9. 没有流氓软件,只有流氓行为
  10. iOS开发 发布之后的Crash错误反馈(二)
  11. 初中数学抽象教学的案例_初中数学教学反思案例
  12. S3C2440开发板烧录笔记
  13. html css做椭圆,简单实例:用css3画椭圆
  14. 数列极限导出重要无理数
  15. perl pack和unpack的使用详解
  16. 【计算机网络】根据IP地址计算网络地址
  17. bzoj4238 电压
  18. 微服务模式笔记:服务分解策略
  19. 【CMake 语法】(6) CMake 条件、循环、跳出循环
  20. 4.3 使用色阶命令调整图像亮度和对比度 [原创Ps教程]

热门文章

  1. C语言时间库操作-->协调时转本地时
  2. 基于音频指纹技术的微信“摇一摇搜歌”和QQ音乐“听歌识曲”
  3. 现在干什么行业最赚钱,什么行业前景好最赚钱?
  4. 写一个自己的前端手脚架(1)
  5. 迁移到行业标准格式PKCS12
  6. Geography V.S. Geometry
  7. Tushare介绍、安装及使用教程
  8. 【直播活动】阿里巴巴开源大家族加入中科院开源之夏2022
  9. 3D网游中人物的碰撞后反应控制
  10. 读《任正非在2012实验室的讲话》总结