二维码

8.1 实现成员管理的MSP - 数据结构 - 机器学习

1306 人阅读 | 时间:2021年01月15日 01:20
8.1 实现成员管理的MSP - 数据结构 - 机器学习 #daohang ul li t,.reed .riqi,a.shangg,a.xiatt,a.shangg:hover,a.xiatt:hover,a.shang,a.xiat,a.shang:hover,a.xiat:hover,.reed-pinglun-anniu,span.now-page,#daohangs-around,#caidan-tubiao,#daohangs,#daohangs li,#btnPost{background-color:#D10B04;} .dinglanyou1 h3{border-bottom:3px solid #D10B04;} #dibuer{border-top:2px solid #D10B04;}.cebianlan .rongqi h3{border-bottom:1px solid #D10B04;} #edtSearch{border:1px solid #D10B04;} #daohang .zuo ul li{border-right:1px solid #;} #daohang ul li t a{border-top:1px solid #;border-right:1px solid #D10B04;} #daohang ul li t a:hover{border-right:1px solid #;} #daohang .you ul li a:hover,#daohang .zuo ul li a:hover,.reed-pinglun-anniu:hover{background-color:#;} a:hover,.reed h6 a:hover,#dibuer a:hover,.reed .riqiding,.cebianlan .rongqi li a:hover,#pinglun-liebiao ul.fubens li.depth-1 dl dd span.shu a,#pinglun-liebiao ul.fubens li.depth-1 dl dd span.huifuliuyan a:hover,.reed-biaoti h6 span{color:#D10B04;} .reed .kan a{color:#0A0AF5;}.reed .kan a:hover{color:#D10101;} @media screen and (max-width:1492px){a.shang,a.xiat{background:none;} a.xiat:hover,a.shang:hover{background-color:#f9f9f9;background-image:none;text-decoration:none;}} var _hmt = _hmt || [];(function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?b19db5ba3b437a9e8698d2bc8fc64334"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s);})(); var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?b19db5ba3b437a9e8698d2bc8fc64334"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?2d748c9763cfc72fb7d1ccab29f0770d"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?f6d451f3f1be23f3abf240c64c469c1b"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })();

当前位置:首页 » 区块链精品文章 » 正文

(function() { var s = "_" + Math.random().toString(36).slice(2); document.write('
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646201", container: s }); })();
(function() { var s = "_" + Math.random().toString(36).slice(2); document.write('
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646162", container: s }); })();

8.1 实现成员管理的MSP

1427 人参与  2018年10月11日 23:11  分类 : 区块链精品文章  评论

第8章 基于数字证书的成员管理服务

Hyperledger Fabric 1.0基于PKI体系,生成数字证书以标识用户的身份。每个身份和成员管理服务提供商(Membership Service Provider,MSP)的编号进行关联,本章将会介绍如何对用户身份进行认证。

8.1 实现成员管理的MSP

MSP(Membership Service Provider):即成员管理服务提供商,是Hyperledger Fabric 1.0中引入的一个组件,其目的是抽象化各成员之间的控制结构关系。MSP将证书颁发、用户认证、后台的加密机制和协议都进行了抽象。每个MSP可以定义 自己的规则,这些规则包括身份的认证,签名的生成和认证。每个Hyperledger Fabric 1.0区块链网络可以引入一个或者多个MSP来进行网络管理。这样就将成员本身和成员之间的操作、规则和流程都模块化了。

8.1.1 MSP成员的验证

我们先来看一下MSP的成员身份及身份标识符定义:


type identity struct {
    // 身份标识符
    id *IdentityIdentifier
    // X.509证书
    cert *x509.Certificate
    // 公钥
    pk bccsp.Key
    // 所属的MSP
    msp *bccspmsp
}

type IdentityIdentifier struct {
    // MSP标识
    Mspid string
    // 身份编号
    Id string
}

从上面的定义中我们可以看到,成员身份是基于标准的X.509证书的。利用PKI体系给每个成员颁发数字证书,结合所属的MSP进行身份认证和权限控制。根CA证书(Root Certificate)是自签名的证书,用根CA证书的私钥签名生成的证书还可以签发新的证书,形成一个树型结构。中间CA证书(Intermediate Certificate)是由其他CA证书签发的,也可以利用自己的私钥签发新的证书。签发证书是一个信任背书的过程,从根CA证书到最终用户证书形成一个证书信任链(Chain of Trust)。在PKI体系中,可以利用CRL(Certificate Revocation List)或者OCSP(Online Certificate Status Protocol)管理证书的有效性。在超级账本中,MSP利用PKI的部分特性来管理证书的有效性。

1)MSP标识的检查:身份证书都是和MSP绑定的,必须有相同的MSP标识才能验证证书的有效性。Peer节点的Gossip通信和部分系统链码的调用都要求调用者身份和本地MSP标识相同,背书请求在通道管理策略验证的时候也会检查MSP成员是否有写入权限。

2)证书路径的检查:除了MSP标识的检查,还会对证书 签名有效性进行检查,主要是证书路径的检查,校验根CA证书、中间CA证书是否有效,是否有从身份证书到可信根CA证书的有效路径。特别说明一下,在证书 验证的时候并不校验证书的有效期,会强制设置当前时间为证书起始时间的下一秒,这确保有效期验证通过。MSP目录下的cacerts和 intermediatecerts子目录签发的证书都是有效的,证书校验的时候需要检查是否有到可信根证书的有效路径。

3)CRL的检查:最后是检查证书是否被吊销,目前只支持CRL的方式,并不支持OCSP。CRL会包含在本地MSP的crls子目录下,是由CA证书签发的包含被吊销证书序列号的证书文件。在通道的MSP配置中,也会包含CRL列表。在更新通道配置的时候可以发布吊销的证书。

8.1.2 MSP的目录结构

下面先介绍生成MSP目录的一些必要准备工作。

1.MSP的配置说明

在每一个Peer节点和排序服务节点上设置MSP目录后,Peer节点和排序服务节点就有了签名证书,在通道节点之间传输数据时,要验证节点的签名。

为了能够标识MSP,每个MSP需要指定一个名称,如org1、org2等。在通道的MSP成员规则中可以用 MSP名称来代表一个联盟(Consortium)、组织(Organization)或者部门(Organization Division)。若在创世区块中检测到两个MSP用同一个MSP名称,则排序服务节点将启动失败。

MSP的默认实现是基于X.509证书格式的,根据RFC5280文档的内容,给一些MSP的配置参考,如表8-1所示。

表8-1 MSP配置参考

8.1 实现成员管理的MSP - 数据结构 - 机器学习

节点需要进行如下的配置才能使用MSP进行签名或者验签:

1)用于节点签名的签名密钥(目前只支持ECDSA密钥)。

2)通过MSP验证是有效的X.509证书将作为节点证书。

怎么才能是MSP的有效身份(Identity)呢?这需要同时满足如下几个条件:

1)身份证书需要符合X.509证书标准,且有到根CA证书或者中间CA证书可验证的证书路径。

2)身份证书不在证书吊销列表中。

3)在X.509证书的OU字段至少包含一个在MSP中配置的部门。

和普通的X.509证书不同的是,MSP的身份证书是没有有效期的,除非被添加到证书吊销列表中。

2.生成MSP证书

有很多的工具可以生成X.509证书,比如广泛使用的OpenSSL。需要注意的是,在Hyperledger Fabric 1.0中,不支持包含RSA密钥的证书。本例中采用cryptogen工具来生成MSP证书,生成过程如下:


# 下载fabric源码,存放在FABRIC_SRC_DIR目录下
git clone git@github.com:hyperledger/fabric.git,
# 生成工具在$FABRIC_SRC_DIR/hyperledger/fabric/examples/e2e_cli目录下
cd $FABRIC_SRC_DIR/hyperledger/fabric/examples/e2e_cli
# 调用e2e的工具生成证书
./generateArtifacts.sh

执行完以上三步操作就会在目录$FABRIC_SRC_DIR/hyperledger/fabric /examples/e2e_cli下产生crypto-config文件夹。在这个MSP中配置了两个组织(即org1与org2),每个组织下有两个 Peer节点(即peer0和peer1):一个排序服务节点,一个CA节点。部分目录的结构如下所示:


├── ordererOrganizations
│   └── example.com
│       ├── ca
│       │   ├── 4514ec148b0b79b58957131cf0f5d516be4b5d79b10f90f5f63ec208d71c8
                5e1_sk
│       │   └── ca.example.com-cert.pem
│       ├── msp
│       │   ├── admincerts
│       │   │   └── Admin@example.com-cert.pem
│       │   ├── cacerts
│       │   │   └── ca.example.com-cert.pem
│       │   └── tlscacerts
│       │       └── tlsca.example.com-cert.pem
│       ├── orderers
│       │   └── orderer.example.com
│       │       ├── msp
│       │       │   ├── admincerts
│       │       │   │   └── Admin@example.com-cert.pem
│       │       │   ├── cacerts
│       │       │   │   └── ca.example.com-cert.pem
│       │       │   ├── keystore
│       │       │   │   └── 550422b59f3ca8cf0df4a9782f1041d906b9100dab8bdf74
                            409c445efdb96437_sk
│       │       │   ├── signcerts
│       │       │   │   └── orderer.example.com-cert.pem
│       │       │   └── tlscacerts
│       │       │       └── tlsca.example.com-cert.pem
│       │       └── tls
│       │           ├── ca.crt
│       │           ├── server.crt
│       │           └── server.key
│       ├── tlsca
│       │   ├── 88fd39ff8fe5e0d103d804a4a3c8e172b7f6ff5adbcf6182b3cd6c1aa2d68
                fa5_sk
│       │   └── tlsca.example.com-cert.pem
│       └── users
│           └── Admin@example.com
│               ├── msp
│               │   ├── admincerts
│               │   │   └── Admin@example.com-cert.pem
│               │   ├── cacerts
│               │   │   └── ca.example.com-cert.pem
│               │   ├── keystore
│               │   │   └── 000c4fd8fa15b46d1ab0f6d3b538b661585023a1366058c3
                            93e75ecffa343f9a_sk
│               │   ├── signcerts
│               │   │   └── Admin@example.com-cert.pem
│               │   └── tlscacerts
│               │       └── tlsca.example.com-cert.pem
│               └── tls
│                   ├── ca.crt
│                   ├── server.crt
│                   └── server.key
└── peerOrganizations

crypto-config目录下会生成两个目录,ordererOrganizations和 peerOrganizations,它们分别代表排序服务节点和Peer节点的MSP配置信息。peerOrganizations目录下有两个组织 org1.example.com和org2.example.com,子目录结构同ordererOrganizations的 example.com。我们以ordererOrganizations的example.com为例说明每个组织的目录结构,如表8-2所示。

表8-2 组织的目录结构

8.1 实现成员管理的MSP - 数据结构 - 机器学习

MSP目录的说明,如表8-3所示。

表8-3 MSP的目录结构

8.1 实现成员管理的MSP - 数据结构 - 机器学习

一个config.yaml的示例,如下所示:


OrganizationalUnitIdentifiers:
    - Certificate: "cacerts/cacert.pem"
    OrganizationalUnitIdentifier: "fabric-ca"

在每个节点或者用户下除了msp目录,还有一个tls目录,用来进行TLS连接的配置,如表8-4所示。

表8-4 TLS的目录结构

8.1 实现成员管理的MSP - 数据结构 - 机器学习

再来看下crypto-config文件夹,其实只需要设置节点下面对应的MSP就可以了,为了方便节点部署,里面有 一些冗余文件。比如ordererOrganizations/example.com/msp目录下子目录文件都会在orderer Organizations/example.com/orderers/orderer.example.com/msp目录下,这样会增加节点 orderer.example.com对应的签名证书和签名私钥。ordererOrganizations/example.com /orderers/orderer.example.com其实就是管理员ordererOrganizations/users /Admin@example.com。还有根CA证书和TLS根CA证书等也是冗余存储的。

3.配置节点的MSP证书

生成MSP证书后,就可以启动Peer节点和排序服务节点了,配置说明如表8-5所示。

表8-5 MSP配置说明

8.1 实现成员管理的MSP - 数据结构 - 机器学习

一个节选的docker-compose.yaml示例文件如下所示:

orderer.example.com:


orderer.example.com:
        container_name: orderer.example.com
        image: hyperledger/fabric-orderer
        environment:
            - ORDERER_GENERAL_LOGLEVEL=debug
            - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
            - ORDERER_GENERAL_GENESISMETHOD=file
            - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.
              genesis.block
            - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
            - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
            # 使能TLS
            - ORDERER_GENERAL_TLS_ENABLED=true
            - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/
              server.key
            - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/
              server.crt
            - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
        working_dir: /opt/gopath/src/github.com/hyperledger/fabric
        command: orderer
        volumes:
            - ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
            - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
            - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.
             example.com/tls/:/var/hyperledger/orderer/tls
        ports:
            - 7050:7050

    peer0.org1.example.com:
        container_name: peer0.org1.example.com
        extends:
            file: peer-base.yaml
            service: peer-base
        environment:
            - CORE_PEER_ID=peer0.org1.example.com
            - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
            - CORE_PEER_CHAINCODELISTENADDRESS=peer0.org1.example.com:7052
            - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
            - CORE_PEER_LOCALMSPID=Org1MSP
        volumes:
            - /var/run/:/host/var/run/
            - ../crypto-config/peerOrganizations/org1.example.com/peers/
              peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
            - ../crypto-config/peerOrganizations/org1.example.com/peers/
              peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
        ports:
            - 7051:7051
            - 7052:7052
            - 7053:7053

对于配置文件中环境变量和节点YAML之间的映射关系,请参考节的配置参数传递规则。从上面的配置文件可以看出, 节点配置直接用到了cryptogen生成的目录结构文件。排序服务节点orderer.example.com的本地MSP名称是 OrdererMSP,本地MSP路径是crypto-config/ordererOrganizations/example.com /orderers/orderer.example.com/msp,TLS的CA根证书、密钥、证书文件目录是在crypto-config /peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls下。 Peer节点peer0.org1.example.com的本地MSP名称是Org1MSP,本地MSP路径是crypto- config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com /msp,TLS的CA根证书、密钥、证书文件目录是在crypto-config/peerOrganizations /org1.example.com/peers/peer0.org1.example.com/tls下。

8.1.3 MSP的配置最佳实践

本节将详尽地描述能够满足常用场合下的MSP配置最佳实践。

1.组织与MSP之间建立映射关系

我们建议实际的组织和MSP之间建立一一对应关系。也可以选择其他类型的映射关系,我们一起来看一下。

1)一个组织对应多个MSP的情况。这种情况是一个组织有多个部门,从方便管理的角度或者隐私保护的角度而言,每个部门都要设置不同的MSP。每个Peer节点只设置一个MSP,同一组织内不同MSP的Peer节点之间不能互相认证,这样相同组织的不同部门之间不会同步数据。

2)多个组织对应一个MSP。这种情况是同一个联盟的不 同组织之间采用相同的成员管理架构,数据会在不同组织之间同步。在前面的章节中我们已经了解到,在Peer节点之间的Gossip通信中,数据是在相同通 道配置了相同MSP的Peer节点之间同步的。如果多个组织对应一个MSP,则数据就不会限制在组织内部,会跨组织进行同步。

其实这是由MSP定义的粒度问题,一个MSP可以和一个组织对应,也可以和多个组织对应,还可以和一个组织内部的多个部门对应,根据MSP配置好Peer节点后,数据同步就限制在了MSP定义的范围内。

2.一个组织内部实现不同的权限控制

一个组织内部有多个部门,从而实现不同部门的权限控制。有两种方法可以实现这个场景:

(1)给组织内的所有部门定义一个MSP

给Peer节点配置MSP的时候,包含相同的可信根CA证书列表、中间CA证书、管理员证书,不同的Peer节点 设置不同的所属部门。节点所属的部门是利用证书和部门之间映射的OrganizationalUnitIdentifiers定义的,它包含在MSP目录 下的配置文件“config.yaml”中,本章前面已经介绍过。在第3章的相关部分,还介绍过可以按照基于部门验证的方法来定义交易背书策略和通道管理 策略,这样就可以实现不同的权限控制了。这种方法会有一个问题,就是数据实际还是会在不同的Peer节点之间同步。因为Peer节点在识别组织身份类型 OrgIdentityType的时候获取的是MSP标识,它会认为通道内相同MSP的节点都是可以分发数据的。

(2)给组织内的每个部门单独定义MSP

给Peer节点配置MSP的时候,不同部门配置的可信中间CA证书、管理员证书可以是不同的,不同部门成员的证书 路径也是不同的。这种方式解决了所有部门定义在一个MSP中的问题,但是会带来管理上的复杂度。另外一个办法是每个部门都设置不同的MSP,利用证书和部 门之间映射的OrganizationalUnitIdentifiers实现不同部门的权限控制,数据同步仍然会限制在组织的不同部门内,这同样也会有 管理上的复杂度。

3.不同类型的节点分别使用不同的MSP

可能有这样的需求,希望给客户端、Peer节点、排序服务节点分别设置不同的MSP,因为身份信息会包含MSP标 识,设置不同的MSP后就能确定身份类型。这在很多情况下是有用的,比如能够验证背书的确是由Peer节点签名的,而不是由客户端或者排序服务节点签名 的。实际上,这样设置会带来一些问题,我们一起来分析一下。

不同节点类型分别设置不同的MSP,对应的可信中间CA证书也不一样。在通道设置的时候需要包含不同的MSP及其 可信中间CA证书,组织内的不同MSP成员才可以访问通道里的数据。同时背书策略可以指定只有Peer节点对应的MSP成员背书的交易才有效,这就能实现 只能是Peer节点才能背书签名的目的。同一个组织按不同节点类型设置MSP之后,Peer节点都有相同的MSP,Peer节点之间的数据同步不会受到影 响,但会影响Peer节点和客户端之间的交互。

在Peer节点上某些系统链码的调用是和本地MSP相关的,比如只执行本地MSP配置的由管理员发起的安装链码 (install)请求、加入通道(JoinChain)请求等。应用程序执行这类系统调用时还需要用到Peer节点相同MSP的管理员签名密钥和证书。 当然,如果不把这类系统调用功能放在应用程序中去实现,正常的背书请求响应是没有问题的,因为Peer节点接收背书请求检查的是有没有通道的写入权限。因 此可以在配置通道管理策略时增加客户端的MSP,客户端就可以向Peer节点提交请求了。

还有一个问题是,注册事件回调函数的时候,Peer节点只处理和本地MSP相同的客户端发起的请求,这个时候若Peer节点和客户端属于不同的MSP,就会拒绝客户端发起的请求。如果业务依赖事件处理的话,应用程序和Peer节点还是需要采用相同的MSP。

4.区分管理员和CA证书

不要把可信根CA证书或者中间CA证书设置成MSP管理员证书,这样能把成员管理、签发证书与验证证书等不同职责拆分开来,方便管理和问题定位,这其实是一种常见的安全做法。

5.区分根CA证书和TLS的根CA证书

MSP的根CA证书和TLS根CA证书以及相关的中间CA证书需要存放在不同的文件夹中,这是为了避免混淆不同类别的证书。虽然并没有禁止根CA证书和TLS根CA证书采用相同的证书,在生产环境中建议还是区分开。

6.吊销已经颁发的证书

由于权限管理或者其他方面的原因,已经颁发的证书是可以被吊销的。参考前面MSP成员证书的有效性验证过程,吊销已颁发的证书有多种办法:

1)删除中间CA证书:删除intermediatecerts目录下的证书,这样由中间CA证书签发的证书都属于无效证书。

2)增加CRL列表:可以把中间CA证书或者单个证书添加到CRL列表中。

重新配置节点本地MSP的时候,要删除intermediatecerts目录下的证书或者在crls目录下增加CRL列表证书就可以了。重新配置通道MSP的时候,需要提交CONFIG_UPDATE的交易请求,生效以后修改排序服务节点和Peer节点的MSP配置。


来源:我是码农,转载请保留出处和链接!

本文链接:http://www.54manong.com/?id=1060

(function() { var s = "_" + Math.random().toString(36).slice(2); document.write('
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646208", container: s }); })();
(function() { var s = "_" + Math.random().toString(36).slice(2); document.write('
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646147", container: s }); })();
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdPic":"","bdStyle":"0","bdSize":"16"},"share":{},"image":{"viewList":["qzone","tsina","tqq","renren","weixin"],"viewText":"分享到:","viewSize":"16"},"selectShare":{"bdContainerClass":null,"bdSelectMiniList":["qzone","tsina","tqq","renren","weixin"]}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
区块链是什么  

微信号:qq444848023    QQ号:444848023

加入【我是码农】QQ群:864689844(加群验证:我是码农)

<< 上一篇 下一篇 >>
(function() { var s = "_" + Math.random().toString(36).slice(2); document.write('
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646186", container: s }); })();
(function() { var s = "_" + Math.random().toString(36).slice(2); document.write('
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646175", container: s }); })();
搜索

网站分类

标签列表

最近发表

    (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https'){ bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else{ bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();

全站首页 | 数据结构 | 区块链| 大数据 | 机器学习 | 物联网和云计算 | 面试笔试

var cnzz_protocol = (("https:" == document.location.protocol) ? "https://" : "http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1276413723'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s23.cnzz.com/z_stat.php%3Fid%3D1276413723%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));本站资源大部分来自互联网,版权归原作者所有!

jQuery(document).ready(function($){ /* prepend menu icon */ $('#daohangs-around').prepend('
'); /* toggle nav */ $("#caidan-tubiao").on("click", function(){ $("#daohangs").slideToggle(); $(this).toggleClass("active"); }); });

©著作权归作者所有:来自ZhiKuGroup博客作者没文化的原创作品,如需转载,请注明出处,否则将追究法律责任 来源:ZhiKuGroup博客,欢迎分享。

评论专区
  • 昵 称必填
  • 邮 箱选填
  • 网 址选填
◎已有 0 人评论
搜索
作者介绍
30天热门
×
×
本站会员尊享VIP特权,现在就加入我们吧!登录注册×
»
会员登录
新用户注册
×
会员注册
已有账号登录
×