《PG源码学习--7.角色管理》

一.背景

PostgreSQL实现基于角色的访问控制机制,通过对角色的权限设置,实现对数据库对象如关系表的操作(如增加、删除、查询等)

二.系统表

pg_authid是角色系统表,pg_roles是基于pg_authid的视图,实习对密码的屏蔽。
1.pg_authid

属性 数据类型 说明
oid oid 唯一标识
rolname name 角色名称
rolsuper bool 超级用户权限
rolinherit bool 自动继承所属组权限
rolcreaterole bool 创建角色权限
rolcreatedb bool 创建数据库权限
rolcanlogin bool 登录权限
rolreplication bool 复制权限
rolbypassrls bool 行安全策略
rolconnlimit int4 连接限制
rolpassword text 密码
rolvaliduntil timestamptz 过期时间,不设置为空

2.pg_auth_members

属性 数据类型 说明
oid oid 唯一标识
roleid oid 父角色标识
member oid 子角色标识
grantor oid 建立父子关系的标识
admin_option bool 如果member可以把roleid角色的成员关系赋予其他角色,则为真

三.数据结构

1.声明

typedef struct CreateRoleStmt
{
   
   NodeTag       type;
   RoleStmtType stmt_type;       /* ROLE/USER/GROUP */
   char      *role;        /* role name */
   List      *options;      /* List of DefElem nodes */
} CreateRoleStmt;

2.角色属性
CREATE ROLE user1 WITH PASSWORD ‘12345’; 当前的属性是密码,值为’12345’。以stmt->options链表的形式表达。

typedef struct DefElem
{
   
   NodeTag       type;
   char      *defnamespace;  /* NULL if unqualified name */
   char      *defname;
   Node      *arg;         /* a (Value *) or a (TypeName *) */
   DefElemAction defaction;   /* unspecified action, or SET/ADD/DROP */
   int          location;     /* token location, or -1 if unknown */
} DefElem;

四.核心代码

1.创建角色的流程
在这里插入图片描述
2.backend\commands\user.c

Oid
CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
{
   
   Relation   pg_authid_rel;
   TupleDesc  pg_authid_dsc;
   HeapTuple  tuple;
   Datum     new_record[Natts_pg_authid];
   bool      new_record_nulls[Natts_pg_authid];
   Oid          roleid;
   ListCell   *item;
   ListCell   *option;
   char      *password = NULL;   /* user password */
   bool      issuper = false;   /* Make the user a superuser? */
   bool      inherit = true; /* Auto inherit privileges? */
   bool      createrole = false; /* Can this user create roles? */
   bool      createdb = false;  /* Can the user create databases? */
   bool      canlogin = false;  /* Can this user login? */
   bool      isreplication = false; /* Is this a replication role? */
   bool      bypassrls = false; /* Is this a row security enabled role? */
   int          connlimit = -1; /* maximum connections allowed */
   List      *addroleto = NIL;   /* roles to make this a member of */
   List      *rolemembers = NIL; /* roles to be members of this role */
   List      *adminmembers = NIL; /* roles to be admins of this role */
   char      *validUntil = NULL; /* time the login is valid until */
   Datum     validUntil_datum;  /* same, as timestamptz Datum */
   bool      validUntil_null;
   DefElem    *dpassword = NULL;
   DefElem    *dissuper = NULL;
   DefElem    *dinherit = NULL;
   DefElem    *dcreaterole = NULL;
   DefElem    *dcreatedb = NULL;
   DefElem    *dcanlogin = NULL;
   DefElem    *disreplication = NULL;
   DefElem    *dconnlimit = NULL;
   DefElem    *daddroleto = NULL;
   DefElem    *drolemembers = NULL;
   DefElem    *dadminmembers = NULL;
   DefElem    *dvalidUntil = NULL;
   DefElem    *dbypassRLS = NULL;

   /* The defaults can vary depending on the original statement type */
   switch (stmt->stmt_type)
   {
   
      case ROLESTMT_ROLE:
         break;
      case ROLESTMT_USER:
         canlogin = true;
         /* may eventually want inherit to default to false here */
         break;
      case ROLESTMT_GROUP:
         break;
   }

   /* Extract options from the statement node tree */
   foreach(option, stmt->options)
   {
   
      DefElem    *defel = (DefElem *) lfirst(option);

      if (strcmp(defel->defname, "password") == 0)
      {
   
         if (dpassword)
            ereport(ERROR,
                  (errcode(ERRCODE_SYNTAX_ERROR),
                   errmsg("conflicting or redundant options"),
                   parser_errposition(pstate, defel->location)));
         dpassword = defel;
      }
      else if (strcmp(defel->defname, "sysid") == 0)
      {
   
         ereport(NOTICE,
               (errmsg
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值