Hyperledger Fabric:实现链码级访问控制

时间:2019-05-04 14:21:11

标签: hyperledger-fabric hyperledger hyperledger-chaincode chaincode

我想对某些方法实施链码级访问控制。因此,例如,我希望只有在执行请求的用户具有与世界状态下请求的资产字段匹配的证书身份时,才能执行被调用的chaincode方法。

https://hyperledger-fabric.readthedocs.io/en/release-1.4/chaincode4ade.html中,官方文档说:

“ Chaincode可以通过调用GetCreator()函数来利用客户端(提交者)证书进行访问控制决策。此外,Go shim提供了扩展API,这些API从提交者的证书中提取客户端身份,可用于访问控制决策,无论是否是基于客户端身份本身,组织身份或客户端身份属性的。

例如,表示为键/值的资产可以将客户的身份包括为值的一部分(例如,作为表示资产所有者的JSON属性),并且只有该客户才能被授权对将来的键/值。客户端身份库扩展API可以在链码中使用,以检索此提交者信息以做出此类访问控制决策。”

这完全反映了我的情况:我的资产包含字段所有者,并且我希望只有该资产所有者的用户才能对资产执行remove方法,即,如果其身份(用户名)与所有者字段。

我的问题是,官方文档中提供的解决方案描述了使用“客户端身份(cid)库”(https://github.com/hyperledger/fabric/tree/master/core/chaincode/shim/ext/cid)从证书中提取用户信息的可能性。但就我而言,我有Java和Javascript链代码,而且(我认为)我只能使用GetCreator()方法,该方法以字节数组的形式输出用户证书。

如何从证书中提取所需的信息?可能吗?可以使用我的Java和Javascript链码中的CID库吗?

2 个答案:

答案 0 :(得分:1)

我也在寻找此功能,但是现在似乎已经添加了它。 FAB-15895将ClientIdentity.java添加到Java链码中(请参阅commit),该查询允许在证书中查询信息。希望它将成为Fabric下一个版本-v1.4.4的一部分。

答案 1 :(得分:0)

CID库只是一个语法糖包装器,可帮助在链码中使用身份进行操作,实质上是在GoLang中提取信息的方法或方式是:


    serializedID, _ := stub.GetCreator()

    sId := &msp.SerializedIdentity{}
    err := proto.Unmarshal(serializedID, sId)
    if err != nil {
        return shim.Error(fmt.Sprintf("Could not deserialize a SerializedIdentity, err %s", err))
    }

    bl, _ := pem.Decode(sId.IdBytes)
    if bl == nil {
        return shim.Error(fmt.Sprintf("Could not decode the PEM structure"))
    }
    cert, err := x509.ParseCertificate(bl.Bytes)
    if err != nil {
        return shim.Error(fmt.Sprintf("ParseCertificate failed %s", err))
    }

    fmt.Println(cert)

这可以在Java中通过以下几行完成:

        try {
            Identities.SerializedIdentity identity = Identities.SerializedIdentity.parseFrom(stub.getCreator()); 
            StringReader reader = new StringReader(identity.getIdBytes().toStringUtf8()); 
            PemReader pr = new PemReader(reader); 
            byte[] x509Data = pemReader.readPemObject().getContent();
            CertificateFactory factory = CertificateFactory.getInstance("X509"); 
            X509Certificate certificate = factory.generateCertificate(new ByteArrayInputStream(x509Data));

        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }