Fabric链码获取用户证书的方法

在Fabric链码开发过程中,有时候需要获取调用链码的用户信息,比如在一个数据共享的链码中,需要根据用户的信息对数据进行限制访问。幸运的是,Fabric提供了ChaincodeStubInterface接口,其中GetCreator方法可以获取提交请求的用户的相关信息。接口描述如下:

// GetCreator returns `SignatureHeader.Creator` (e.g. an identity)
// of the `SignedProposal`. This is the identity of the agent (or user)
// submitting the transaction.
GetCreator() ([]byte, error)

从GetCreator接口描述中可以看出,GetCreator方法返回的是一个byte数组,而将byte数组转换为string对应的是调用用户identity信息序列号的字符串,如下所示:

\n\007DEFAULT\022\272\006-----BEGIN CERTIFICATE-----\nMIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx\nCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g\nRnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND\nT1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx\nWhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv\ncm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD\nVQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\nAQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf\nEkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud\nEwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H\nossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz\nPzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI\n-----END CERTIFICATE-----\n

可以看出返回的信息里包含MSPID和用户证书两部分内容,那么如何将MSPID和用户证书分别取取出来哪?可以按照以下步骤。

1. 转换证书信息

通过调用shim.ChaincodeStubInterface接口中的GetCreator接口,实际上返回的是github.com/hyperledger/fabric/protos/msp包中SerializedIdentity对象序列号的字符串,因此,我们只需将查询到的字符串转换回去就可以了。示例代码如下:

creatorByte, err := stub.GetCreator()
// 构造SerializedIdentity方法,并将creator进行Unmarshal
si := &msp.SerializedIdentity{}
err = proto.Unmarshal(creatorByte, si)
if err != nil {
	return "", err
}
fmt.Println("MSPID: " + si.GetMspid())
fmt.Println("Cert: " + string(si.GetIdBytes()))

通过测试,返回的信息如下:

MSPID: DEFAULT
Cert: -----BEGIN CERTIFICATE-----
MIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx
CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g
RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND
T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx
WhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv
cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD
VQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf
EkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud
EwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H
ossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz
PzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI
-----END CERTIFICATE-----

2. 使用govendor导入依赖包

上述的示例代码里面需要依赖github.com/golang/protobuf/proto 包和github.com/hyperledger/fabric/protos/msp 包,而这两个包在ccenv容器并没有打包进去。对于不能访问互联网的环境,install合约的时,会报找不到包的错误,如下所示:

testchaincode.go:8:2: cannot find package "github.com/golang/protobuf/proto" in any of:
    /opt/go/src/github.com/golang/protobuf/proto (from $GOROOT)
    /opt/gopath/src/github.com/golang/protobuf/proto (from $GOPATH)

在这里,我们使用govendor工具将这两个包导入chaincode代码。

首先,进入chaincode项目目录,进行初始化,生成vendor目录和vendor/verdor.json文件。

govendor init

然后,使用govendor fetch获取依赖包

govendor fetch github.com/golang/protobuf/proto
govendor fetch github.com/hyperledger/fabric/protos/[email protected]

这样,就把相关的包导入了vendor目录,其中msp包的版本最好设置为和fabric版本一致。此时,将整个项目目录发送到chaincode对应目录,就可以进行安装、实例和调用操作了。

vendor
├── github.com
│   ├── golang
│   │   └── protobuf
│   │       ├── LICENSE
│   │       └── proto
│   │           ├── clone.go
│   │           ├── decode.go
│   │           ├── deprecated.go
│   │           ├── discard.go
│   │           ├── encode.go
│   │           ├── equal.go
│   │           ├── extensions.go
│   │           ├── lib.go
│   │           ├── message_set.go
│   │           ├── pointer_reflect.go
│   │           ├── pointer_unsafe.go
│   │           ├── properties.go
│   │           ├── table_marshal.go
│   │           ├── table_merge.go
│   │           ├── table_unmarshal.go
│   │           ├── text.go
│   │           └── text_parser.go
│   └── hyperledger
│       └── fabric
│           ├── LICENSE
│           └── protos
│               └── msp
│                   ├── identities.pb.go
│                   ├── identities.proto
│                   ├── msp_config.go
│                   ├── msp_config.pb.go
│                   ├── msp_config.proto
│                   ├── msp_principal.go
│                   ├── msp_principal.pb.go
│                   └── msp_principal.proto
└── vendor.json

3.总结

本文描述了fabric系统中如何在链码中获取调用者的身份信息,并将相关的依赖包倒入chaincode项目。在链码开发中,如果依赖了go语言的包,也可以通过这种方式,将依赖包导入链码工程。

你可能感兴趣的:(hyperledger,区块链)