zoukankan      html  css  js  c++  java
  • 第十章 FISCO BCOS权限控制下的数据上链实操演练

     

    想了解相关区块链开发,技术提问,请加QQ群:538327407

    一、目的

    前面已经完成FISCO BCOS 相关底层搭建、sdk使用、控制台、WeBASE中间件平台等系列实战开发,

    本次进行最后一个部分,体系化管理区块链底层,建立有序的底层控管制度,实现权限化管理。

    完成:链管理、系统管理、数据上链操作等。

    其中数据上链分为:合约版本上链、crudService 版本上链等操作。


    二、准备工作:

    在进行之前,我们首先要了解一下,fisco bcos 的底层权限系统介绍。

    https://mp.weixin.qq.com/s/QJNk71w4o_cGX2O-1aW29Q

    三、设计理念差异

    1、底层默认是可以部署合约,只有一旦操作 grantDeployAndCreateManager 命令,才开始限制用户部署合约权限

    ps:一开始权限基本开放,而不是像常规系统设计那样,一开始权限为无,等到分配好权限才可以相应的的操作。

    2、底层默认是写表操作,写表操作就有了CRUD等操作,常规的区块链体系是在不断区块打包过程中附加数据,FISCO BCOS 提供写表操作,实质上业务数据可以有修改的权限,

    所以在链搭建好后,就必须限制Update等操作权限,并且在业务设计时候,需要多方去验证修改数据等过程,才可以防止区块链底层数据让高权限的人的篡改。

    ps:与官方人员交谈,提供的例子

    比如官方给出的存证的例子,一个证据X,需要A,B机构确认。先是证据X上链(一笔交易),然后机构A看到证据,
    确认有效(又一笔交易),机构B演的证据,确认有效(又一笔交易)。三笔交易完成业务共识的逻辑。
    别人取证X的时候,读区块链,查看是否A,B都确认过,确认过了,证据X才有效。

    四、场景构想搭建

    我们在底层完成各种系统化的搭建,现在要使用多种方式进行权限管控,以及数据上链等操作。

    1、我们首先要建立链管理员、系统管理员、普通用户。

    2、其次我们要使用控制台 或sdk进行管理员等设定。

    3、对合约的部署权限、以及数据权限更新操作做授权。

    4、在sdk 中配置授权用户的pem、p12密钥的使用。

    5、使用合约操作,进行合约部署,合约CRUD操作。

    6、使用CRUDService 进行数据操作。

    7、使用PermissionService 进行权限控制。

    最后根据我们设定好的权限,完成多个不同身份用户进行的数据操作,这样我们就完成生产环境下的数据上链操作。

    备注:以下操作,可以参考web3sdk单元测试。官方github web3sdk 地址:https://github.com/FISCO-BCOS/web3sdk

     

    五、实操演练

    (一)创建和管理用户

    创建用户,用于后续的管理员设置,进行权限管理设置。

    官方资料:https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/tutorial/account.html

    FISCO BCOS 底层 支持控制台创建账户、sdk 创建账户

    先采用控制台进行基础用户创建,以及基本全是设置

    在console 目录下 使用bash get_account.sh、bash get_account.sh -p 创建不同的账户
    
    Usage: ./get_account.sh
    
    default generate account and store private key in PEM format file(默认生成pem格式用户)
    -p generate account and store private key in PKCS12 format file(默认生成p12格式用户)
    -k [FILE] calculate address of PEM format [FILE](通过pem 私钥文件生成账户地址)
    -P [FILE] calculate address of PKCS12 format [FILE](通过p12 私钥文件生成账户地址)
    -h Help

    创建链管理员 ,pem 格式

    ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh
    [INFO] Account Address : 0x83a37766067ea59eea78135b20a4afc251246e88
    [INFO] Private Key (pem) : accounts/0x83a37766067ea59eea78135b20a4afc251246e88.pem

    创建三个用户

    1、具有 发布合约权限的用户

    ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh -p
    Enter Export Password:123456
    Verifying - Enter Export Password:123456
    [INFO] Account Address : 0xb93bb9276d97f5f75ea574965beab99f72310e45
    [INFO] Private Key (p12) : accounts/0xb93bb9276d97f5f75ea574965beab99f72310e45.p12

    2、系统管理员

    ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh -p
    Enter Export Password:
    Verifying - Enter Export Password:
    [INFO] Account Address : 0xca96eb0e7c70c9117a2b5bda65cbcfc1b37a35c2
    [INFO] Private Key (p12) : accounts/0xca96eb0e7c70c9117a2b5bda65cbcfc1b37a35c2.p12

    3、普通用户

    ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh -p
    Enter Export Password:
    Verifying - Enter Export Password:
    [INFO] Account Address : 0x190b5d0a7ed4754c9226ee96c50cd125ec5720bf
    [INFO] Private Key (p12) : accounts/0x190b5d0a7ed4754c9226ee96c50cd125ec5720bf.p12

    pem登录方式:

    bash ./start.sh 1 -pem accounts/0x83a37766067ea59eea78135b20a4afc251246e88.pem

    p12 登录方式:(需要输入密码)

    bash ./start.sh 1 -p12 accounts/0xb93bb9276d97f5f75ea574965beab99f72310e45.p12

    (二)控制台基本权限设置

    设定账户1为链管理员账户,账户2为系统管理员账户,账户3为普通账户。


    1、链管理员账户拥有权限管理的权限,即能分配权限。

    [group:1]> grantDeployAndCreateManager 0x83a37766067ea59eea78135b20a4afc251246e88
    {
    "code":0,
    "msg":"success"
    }

    2、系统管理员账户可以管理系统相关功能的权限,每一种系统功能权限都需要单独分配,
    具体包括部署合约和创建用户表的权限、管理节点的权限、利用CNS部署合约的权限以及修改系统参数的权限。
    链管理员账户可以授权其他账户为链管理员账户或系统管理员账户,

    [group:1]> grantDeployAndCreateManager 0xb93bb9276d97f5f75ea574965beab99f72310e45
    {
    "code":0,
    "msg":"success"
    }
    
     

    3、也可以授权指定账号可以写指定的用户表,即普通账户。

    用某个用户登录后,使用命令赋予权限,前提是他拥有该权限操作

    权限命令:https://fisco-bcos-documentation.readthedocs.io/zh_CN/release-2.0/docs/manual/permission_control.html


    (三)Sdk下配置

    1、将控制台生成account 目录下的文件copy sdk中。

     applicationContext.xml 文件配置修改,其中包括密钥文件的配置。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="encryptType" class="org.fisco.bcos.web3j.crypto.EncryptType">
            <constructor-arg value="0"/> <!-- 0:standard 1:guomi -->
        </bean>
    
        <bean id="groupChannelConnectionsConfig" class="org.fisco.bcos.channel.handler.GroupChannelConnectionsConfig">
            <property name="allChannelConnections">
                <list>  <!-- 每个群组需要配置一个bean,每个群组可以配置多个节点 -->
                    <bean id="group1"  class="org.fisco.bcos.channel.handler.ChannelConnections">
                        <property name="groupId" value="1" /> <!-- 群组的groupID -->
                        <property name="connectionsStr">
                            <list>
                          
                                <value>对应的节点ip:20201</value>
                                <value>对接节点ip:20200</value>  <!-- IP:channel_port -->
                            
                            </list>
                        </property>
                    </bean>
                    <bean id="group2"  class="org.fisco.bcos.channel.handler.ChannelConnections">
                        <property name="groupId" value="2" /> <!-- 群组的groupID -->
                        <property name="connectionsStr">
                            <list>
                                <value>127.0.0.1:20202</value>
                                <value>127.0.0.1:20203</value>
                            </list>
                        </property>
                    </bean>
                </list>
            </property>
        </bean>
    
    <bean id="channelService" class="org.fisco.bcos.channel.client.Service" depends-on="groupChannelConnectionsConfig"> <property name="groupId" value="1" /> <!-- 配置连接群组1 --> <property name="agencyName" value="fisco" /> <!-- 配置机构名 --> <property name="allChannelConnections" ref="groupChannelConnectionsConfig"></property> </bean> <bean id="p12" class="org.fisco.bcos.channel.client.P12Manager" init-method="load" > <property name="password" value="123456" /> <property name="p12File" value="classpath:0xb93bb9276d97f5f75ea574965beab99f72310e45.p12" /> </bean> <bean id="pem" class="org.fisco.bcos.channel.client.PEMManager" init-method="load" > <property name="pemFile" value="classpath:0x83a37766067ea59eea78135b20a4afc251246e88.pem" /> </bean> </beans>

    如果要写单元测试

    也要把相关配置copy 过去,详情见图

     (四)单元测试 合约部署,CRUD操作

    1、基础设置,包括具有部署合约权限用户设置

      private Credentials credentials;
        private static BigInteger gasPrice = new BigInteger("300000000");
        private static BigInteger gasLimit = new BigInteger("300000000");
        @Autowired
        Web3j web3j;
        protected String tempDirPath =  new File("src/main/resources/").getAbsolutePath();
        //这很重要,没有这个无法通过
        @Before
        public void setUp() throws Exception {
            ApplicationContext context =
                    new ClassPathXmlApplicationContext(
                            "classpath:applicationContext-keystore-sample.xml");
            // test p12
            P12Manager p12 = context.getBean(P12Manager.class);
            ECKeyPair p12KeyPair = p12.getECKeyPair();
    
            System.out.println("p12KeyPair.getPrivateKey() = " + p12KeyPair.getPrivateKey().toString(16));
            System.out.println("p12KeyPair.getPublicKey() = " + p12KeyPair.getPublicKey().toString(16));
    
    
            ECPublicKey publicKey = (ECPublicKey) p12.getPublicKey();
            byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
            BigInteger publicKeyValue =
                    new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));
    
            System.out.println("publicKeyValue = " + publicKeyValue.toString(16));
    
            credentials = Credentials.create(p12KeyPair);//这里将具有合约部署权限的用户设置进去,当前操作对象
    
            System.out.println("credentials  getAddress= " + credentials.getAddress());
        }
    
        @After
        public void tearDown() {
        }

    2、部署合约

     @Test
        //1、部署合约
        public void DeployTable() throws Exception {
            // 部署合约
            TableTemp tableTemp = TableTemp.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send();
    
            if (tableTemp != null) {
                System.out.println("TableTemp address is: " + tableTemp.getContractAddress());
            }
    
        }

    3、创建表合约操作,此时,需要用到部署合约时候生成的地址

     //2、创建表操作
        @Test
        public void CreateTableTest()throws Exception  {
            String contractAddress = "0xb4245b7b6cc33f8f65d8bf37f084dec3e31ca573";//合约部署时候的生成的地址
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
            TransactionReceipt receipt = tableTemp.create().send();
            System.out.println("AssetTest.AssetTransfer receipt="+receipt.toString());
        }

    4、插入表操作(合约地址改为自己测试的,笔者由于多次单元测试,合约地址不同)

     //3.1、插入表操作 无返回值操作
        @Test
        public void InsertTableTest()throws Exception  {
            String contractAddress = "0x215ac9f7af5766ff45d80082091856b54fcf4308";
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
    
            String name = "wq";
            int item_id = Integer.parseInt("2");
            String item_name ="aaa";
            String item_address ="ddd";
            tableTemp.insert(name, BigInteger.valueOf(item_id), item_name,item_address).send();
          
        }
    
        //3.2、插入表操作
        @Test
        public void InsertTableByReturnTest()throws Exception  {
            String contractAddress = "0xb4245b7b6cc33f8f65d8bf37f084dec3e31ca573";
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
    
            String name = "ak";
            int item_id = Integer.parseInt("1");
            String item_name ="tempUser";
            String item_address ="北京";
    
    
            TransactionReceipt send = tableTemp.insert(name, BigInteger.valueOf(item_id), item_name, item_address).send();
            System.out.println(" send= "+send.toString());
         
        }

    5、删除表操作

     //4.1删除表数据操作
        @Test
        public void DeleteTableTest()throws Exception  {
            String contractAddress = "0x215ac9f7af5766ff45d80082091856b54fcf4308";
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
            TransactionReceipt send=  tableTemp.remove("ak",BigInteger.valueOf(1)).send();
    
            System.out.println("send.toString() = " + send.toString());
            System.out.println("send.getContractAddress() = " + send.getContractAddress());
            System.out.println("send.getBlockHash() = " + send.getBlockHash());
            System.out.println("send.getBlockNumber() = " + send.getBlockNumber());
    
        }
        //4.2删除表数据操作
        @Test
        public void DeleteTableByReturnTest()throws Exception  {
            String contractAddress = "0xb4245b7b6cc33f8f65d8bf37f084dec3e31ca573";
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
    
            int item_id = Integer.parseInt("1");
            String name="ak";
            RemoteCall<TransactionReceipt> remove =
                    (RemoteCall<TransactionReceipt>) tableTemp.remove(name,BigInteger.valueOf(item_id));
    
            TransactionReceipt transactionReceipt = remove.send();
            List<TableTemp.RemoveResultEventResponse> removeResultEvents =
                    tableTemp.getRemoveResultEvents(transactionReceipt);
            if (removeResultEvents.size() > 0) {
                TableTemp.RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0);
                System.out.println(
                        "removeCount = " + reomveResultEventResponse.count.intValue());
            } else {
                System.out.println("tableTemp table does not exist.");
            }
    
    
        }

    6、查询表操作,由于合约返回字段有限,最好不要超过三个,有可能会报错。如果使用返回strust是可以解决该问题的。

    开头加上这个:pragma experimental ABIEncoderV2;
    返回值可以用struct

      //5、表查询
        @Test
        public void SelectTableTest() throws  Exception{
            String contractAddress = "0xa94c07af700bf2e435a3051b0a98f2f75eca0298";
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
            Tuple3<List<byte[]>, List<BigInteger>, List<byte[]>> lists = tableTemp.select("ak").send();
            //这个只是返回合约执行的结果,不会返回本身数据库表数据
         //   System.out.println("send.toString() = " + send.toString());
            List<byte[]> value1 = lists.getValue1();
            List<BigInteger> value2 = lists.getValue2();
            List<byte[]> value3 = lists.getValue3();
    
            for (int i = 0; i < value1.size(); i++) {
                String name = new String(value1.get(i));
    
                System.out.println("name = " + name);
                int item_id = value2.get(i).intValue();
    
                System.out.println("item_id = " + item_id);
                String item_name = new String(value3.get(i));
    
                System.out.println("item_name = " + item_name);
            }
    
        }

    7、更新表操作,当前笔者还没设置更新操作权限,所以该方法是可以修改表数据

    //6、表更新
        @Test
        public void UpateTableTest() throws  Exception{
            String contractAddress = "0xb940c1966a6ce94484f0fdabd3bb8cb38edc9dfd";
            // 加载合约地址
            TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
            TransactionReceipt ak=  tableTemp.update("ak",BigInteger.valueOf(1),"121","wew").send();
            System.out.println("ak.toString() = " + ak.toString());
        }

    ps:由于合约操作在实际中返回值等问题,可能存在许多不确定等坑,所以和官方聊之后,可以使用crudService进行表的操作。

    (五) 采用CrudService 进行表数据操作

    CrudService 本身就是对表的操作的服务封装。

    这里的单元测试需要用到 基础设置TestBase,主要配置具有表操作权限的用户。

    package customTest;
    
    import java.math.BigInteger;
    import java.util.Arrays;
    
    import org.bouncycastle.jce.interfaces.ECPublicKey;
    import org.fisco.bcos.channel.client.P12Manager;
    import org.fisco.bcos.channel.client.Service;
    import org.fisco.bcos.web3j.crypto.Credentials;
    import org.fisco.bcos.web3j.crypto.ECKeyPair;
    import org.fisco.bcos.web3j.protocol.Web3j;
    import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService;
    import org.fisco.bcos.web3j.tx.gas.StaticGasProvider;
    import org.junit.AfterClass;
    import org.junit.BeforeClass;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestBase {
      public static ApplicationContext context = null;
      public static Credentials credentials;
    
      protected static Web3j web3j;
      protected static BigInteger gasPrice = new BigInteger("30000000");
      protected static BigInteger gasLimit = new BigInteger("30000000");
      protected static String address;
      protected static BigInteger blockNumber;
      protected static String blockHash;
      protected static String txHash;
    
      @BeforeClass
      public static void setUpBeforeClass() throws Exception {
    
          context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    
        Service service = context.getBean(Service.class);
        service.run();
    
        ChannelEthereumService channelEthereumService = new ChannelEthereumService();
        channelEthereumService.setChannelService(service);
    
        web3j = Web3j.build(channelEthereumService, service.getGroupId());
    
        ApplicationContext context =
                new ClassPathXmlApplicationContext(
                        "classpath:applicationContext-keystore-sample.xml");
        // test p12
        P12Manager p12 = context.getBean(P12Manager.class);
        ECKeyPair p12KeyPair = p12.getECKeyPair();
    
        System.out.println("p12KeyPair.getPrivateKey() = " + p12KeyPair.getPrivateKey().toString(16));
        System.out.println("p12KeyPair.getPublicKey() = " + p12KeyPair.getPublicKey().toString(16));
    
    
        ECPublicKey publicKey = (ECPublicKey) p12.getPublicKey();
        byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
        BigInteger publicKeyValue =
                new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));
    
        System.out.println("publicKeyValue = " + publicKeyValue.toString(16));
    
        credentials = Credentials.create(p12KeyPair);
    
        System.out.println("credentials  getAddress= " + credentials.getAddress());
      }
    
      @AfterClass
      public static void setUpAfterClass() throws Exception {
        ((ClassPathXmlApplicationContext) context).destroy();
      }
    }

    以下是crudservice 的单元测试全过程操作,依法操作就可以了,关键地方已经有了注释。

    package customTest;
    
    import org.bouncycastle.jce.interfaces.ECPublicKey;
    import org.fisco.bcos.Application;
    import org.fisco.bcos.channel.client.P12Manager;
    import org.fisco.bcos.temp.TableTemp;
    import org.fisco.bcos.web3j.crypto.Credentials;
    import org.fisco.bcos.web3j.crypto.ECKeyPair;
    import org.fisco.bcos.web3j.precompile.crud.CRUDService;
    import org.fisco.bcos.web3j.precompile.crud.Condition;
    import org.fisco.bcos.web3j.precompile.crud.Entry;
    import org.fisco.bcos.web3j.precompile.crud.Table;
    import org.fisco.bcos.web3j.protocol.Web3j;
    import org.fisco.bcos.web3j.tx.gas.StaticGasProvider;
    import org.junit.After;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.test.context.junit4.SpringRunner;
    import java.io.File;
    import java.math.BigInteger;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    
    /*
    * 1、继承 TestBase,配置文件在main的java的resources中applicationContext.xml
    * */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Application.class)
    public class CRUDServiceTest extends TestBase{
        //这里如果设置了权限,那么必须权限用户才可以使用,请看TestBase 中的改造,credentials
        private CRUDService crudSerivce = new CRUDService(web3j, credentials);
    
        @SuppressWarnings("unchecked")
        @Test
        public void CreateTest() throws Exception {
    
            String tableName = "t_item2";
            String key = "name";
            String valueFields  = "item_id, item_name,item_address,item_count";
            Table table = new Table(tableName, key, valueFields);
    
            // create table
            int resultCreate = crudSerivce.createTable(table);
            Assert.assertEquals(resultCreate, 0);
    
    
        }
        @SuppressWarnings("unchecked")
        @Test
        public  void Insert()throws Exception{
    
            String tableName = "t_item2";
            String key = "name";
    
            Table table = new Table(tableName, key);
            int insertResult = 0;
            int num = 5;
            for(int i = 1; i <= num; i++)
            {
                Entry insertEntry = table.getEntry();
                insertEntry.put("item_id", "q");
                insertEntry.put("item_name", "q"+i);
                insertEntry.put("item_address", "q"+i);
                insertEntry.put( "item_count",BigInteger.valueOf(i).toString());
                table.setKey("q");
                insertResult += crudSerivce.insert(table, insertEntry);
            }
            Assert.assertEquals(insertResult, num);
    
        }
        @SuppressWarnings("unchecked")
        @Test
        public  void  Select()throws Exception{
            String tableName = "t_item2";
            String key = "name";
            Table table = new Table(tableName, key);
            // select records
            Condition condition1 = table.getCondition();
            condition1.EQ("name", "q");
            condition1.EQ("item_id", "q");
           // condition1.Limit(1);
            table.setKey("q");//查询记录sql语句必须在where子句中提供表的主键字段值。
    
            List<Map<String, String>> resultSelect1 = crudSerivce.select(table, condition1);
            Assert.assertEquals(resultSelect1.get(0).get("name"), "q");
            Assert.assertEquals(resultSelect1.get(0).get("item_id"), "q");
            Assert.assertEquals(resultSelect1.get(0).get("item_name"), "q1");
        }
        @SuppressWarnings("unchecked")
        @Test
        public void Update() throws Exception{
            String tableName = "t_item2";
            String key = "name";
            Table table = new Table(tableName, key);
            int num = 5;
            table.setKey("q");//查询记录sql语句必须在where子句中提供表的主键字段值。
            Entry updateEntry = table.getEntry();
            updateEntry.put("item_id", "徐徐吹v下次v");
            updateEntry.put("item_name", "121212");
            Condition updateCondition = table.getCondition();
            updateCondition.EQ("name", "q");
            updateCondition.EQ("item_id", "aaaaa");
            int updateResult = crudSerivce.update(table, updateEntry, updateCondition);
            Assert.assertEquals(updateResult, num);
        }
    }

    ps:上述操作除了创建表有权限用户需要操作,其他的操作任意用户均可以操作。

    (六)进行权限操作

    本例子,就是通过第一次创建表操作,无授权和有授权等模式多次测试,从而进行验证当我们设置表更新权限后,没有表更新权限的用户是无法进行更新表操作的,赋予这个用户更新表操作的权限后,就可以进行表更新操作。

    package customTest;
    
    import org.fisco.bcos.channel.client.PEMManager;
    import org.fisco.bcos.temp.TableTemp;
    import org.fisco.bcos.web3j.crypto.Credentials;
    import org.fisco.bcos.web3j.crypto.ECKeyPair;
    import org.fisco.bcos.web3j.precompile.crud.CRUDService;
    import org.fisco.bcos.web3j.precompile.crud.Condition;
    import org.fisco.bcos.web3j.precompile.crud.Entry;
    import org.fisco.bcos.web3j.precompile.crud.Table;
    import org.fisco.bcos.web3j.precompile.permission.PermissionService;
    import org.fisco.bcos.web3j.tx.gas.StaticGasProvider;
    import org.junit.Assert;
    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    
    public class PermissionTest extends TestBase {
    
    
    
        @Test
        // 授权新创建用户的权限,测试它部署合约的权限,正常不授权无法部署
        public void PermissionDeploy() throws Exception {
    
            //1、初始化创建一个用户,没有在底层注册过的
            String tempAddress="0x80e3c3f1f1140fbc550fbfdaa318073af373141d";
            String tempPriKey="9265efb6b860ef244f4fbe3dd445f7829e86d11226573190c026323f77ebcd22";
            String tempPublicKey="1f9c09a4df7e336961c06e1f2373fb2ef6a1b642c444652a7a5a84b04bdc668431bbddab4a1665cb382d6a94aee9ff18bf88210bae7a2388315b2bc5253bcaa";
    
    
            //pem  链管理员进行操作,对新用户进行合约部署权限授权
            PEMManager pem = context.getBean(PEMManager.class);
            ECKeyPair pemKeyPair = pem.getECKeyPair();
    
            //1、链管理员操作 授权新用户的可以发布和部署合约
            credentials = Credentials.create(pemKeyPair);
             PermissionService permissionService = new PermissionService(web3j, credentials);
            String s = permissionService.grantDeployAndCreateManager(tempAddress);
            System.out.println("s = " + s);//这个是授权状态
    
            //2、使用新用户新合约部署测试
            Credentials userCredentials=Credentials.create(tempPriKey,tempPublicKey);
            // 部署合约
            TableTemp tableTemp = TableTemp.deploy(web3j, userCredentials, new StaticGasProvider(gasPrice, gasLimit)).send();
    
            if (tableTemp != null) {
                System.out.println("TableTemp address is: " + tableTemp.getContractAddress());
            }
    
        }
        @Test
        // 授权新创建用户的权限,用户表操作修改权限
        public void PermissionGrantUserTable() throws Exception {
    
            //1、初始化创建一个用户,没有在底层注册过的
            String tempAddress="0x80e3c3f1f1140fbc550fbfdaa318073af373141d";
            String tempPriKey="9265efb6b860ef244f4fbe3dd445f7829e86d11226573190c026323f77ebcd22";
            String tempPublicKey="1f9c09a4df7e336961c06e1f2373fb2ef6a1b642c444652a7a5a84b04bdc668431bbddab4a1665cb382d6a94aee9ff18bf88210bae7a2388315b2bc5253bcaa";
    
    
            //pem  链管理员进行操作,对新用户进行合约部署权限授权
            PEMManager pem = context.getBean(PEMManager.class);
            ECKeyPair pemKeyPair = pem.getECKeyPair();
    
            //1、链管理员操作 授权新用户的可以发布和部署合约
            credentials = Credentials.create(pemKeyPair);
            PermissionService permissionService = new PermissionService(web3j, credentials);
            String s = permissionService.grantUserTableManager("t_item2",tempAddress);
            System.out.println("s = " + s);//这个是授权状态
    
            //2、使用新用户进行表更新 操作
            Credentials userCredentials=Credentials.create(tempPriKey,tempPublicKey);
             //完成后,测试表操作中update操作看看是否可以成功
            CRUDService crudSerivce = new CRUDService(web3j, userCredentials);
            String tableName = "t_item2";
            String key = "name";
            Table table = new Table(tableName, key);
            int num = 5;
            table.setKey("q");//查询记录sql语句必须在where子句中提供表的主键字段值。
            Entry updateEntry = table.getEntry();
            updateEntry.put("item_id", "徐徐吹v下次v");
            updateEntry.put("item_name", "121212");
            Condition updateCondition = table.getCondition();
            updateCondition.EQ("name", "q");
            updateCondition.EQ("item_id", "aaaaa");
            int updateResult = crudSerivce.update(table, updateEntry, updateCondition);
            Assert.assertEquals(updateResult, num);
    
            //结果测试成功,使用授权用户操作的表,可以进行更新操作;否则,不具备这个权限的用户,是无法操作的
        }
    
    }

    六、总结

    根据本篇教程,可以完成底层权限设置、以及sdk实际权限控制操作、最后实现数据上链等等。读者可以根据自己的业务需求修改表结构,依照上述流程可以在生产环境中大致进行业务开发。

    系列教程到此,暂时告一段落,基本从头到尾可以按照每一章节对FISCO BCOS 流程从头到尾进行一次模拟生产环境的实践。

    读后感觉不错,有收获可以微信请作者喝杯咖啡,读后有疑问请加微信,拉群研讨,注明来意

  • 相关阅读:
    3.24课堂
    3.23作业
    3.23课堂
    3.20作业
    3.20课堂
    3.19作业
    3.19课堂
    3.18课堂
    3.18作业
    46、表与表的连接
  • 原文地址:https://www.cnblogs.com/linbin524/p/11303365.html
Copyright © 2011-2022 走看看