SQLite sqlite3_set_authorizer调用例程

sqlite3_set_authorizer

大部分的参考资料,都是写明了注册授权函数这几个简单的字面意思而已,在实际上,可以将一个如下面格式的my_authorizer函数,注册到SQLite语句的解释执行语句当中,并且最先被执行,就像是一个钩子,对sql语句进行一些访问的控制,类似于网络数据包的netfilter。

如下是一个简单的例子:

#include <iostream>
#include "sqlite/sqlite3.h"
using namespace std;

/*
该注册的回调函数,禁止用户删除任何的表,实际上,第三个参数
会传递进来当前操作的表的名称,可以通过和该值进行匹配,是否
需要对该表进行操作,当然由于pszString是一个无符号整型,如果
有多个参数想传递进来,可以设置sqlite3_set_authorizer的第三个
参数为结构体,然后通过将pszString进行类型的强制转换,返回
SQLITE_OK,表示继续执行,返回SQLITE_DENY表示拒绝执行
*/
int my_authorizer(void* pszString, 
                  int nCode,/*当前SQL解析模块正在执行的操作码*/
                  const char* psz1,/*由SQL解析模块传递进来当前操作的数据库表,由操作码决定是否为空*/
                  const char* psz2,
                  const char* psz3,
                  const char* psz4)
{
  int nNotPermitCode = *(int*)pszString;
  if (nNotPermitCode == 11)
  {
    printf("can not execute drop\n");
    return SQLITE_DENY;
  }  
  return SQLITE_OK;
}

int main()
{
  int rc = 0;
  sqlite3* db = NULL;
  char* pdbName = "test0.db";
  char* pszErrMsg = NULL;

  rc = sqlite3_open_v2(pdbName,&db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,NULL);
  

  char* pszCreateTb1 = "create virtual table geo_test1 using rtree_i32(id, minx, maxx)";
  rc = sqlite3_exec(db,pszCreateTb1, 0, 0, &pszErrMsg);

  char* pszInsertsql1 = "insert into geo_test1 values(1, 400, 400)";
  rc = sqlite3_exec(db,pszInsertsql1, 0, 0, &pszErrMsg);

  char* pszDropTable = "drop table geo_test1";

  /*
  授权动作编码(Authorizer Action Codes)
  摘自:https://www.sqlite.org/c3ref/c_alter_table.html
  每一种授权操作码都会传递不同的参数给授权注册函数,详细参考
  网址。11是删除数据库表的授权操作码,当调用授权注册函数的时候
  第三个字符串将获得当前被操作的表的名称。
  */
  int nNotPermitCode = 11;
  /*
  第三个参数是传递给授权注册函数的参数值
  */
  sqlite3_set_authorizer(db, my_authorizer, &nNotPermitCode);

  sqlite3_stmt* statement;

  rc = sqlite3_prepare_v2(db, pszDropTable, -1, &statement, NULL);
  /*
  单步调试到perr的错误信息:no authored,表示无权操作
  */
  const char* pszErr = sqlite3_errmsg(db);


  sqlite3_close(db);
  

  return 0;
}



你可能感兴趣的:(SQLite sqlite3_set_authorizer调用例程)