在postgresql中,database,schema,table之间关系 从逻辑上看,schema、table都是位于database之下。在postgres数据库下建立表(相当于建立在public schema下),理解pg下的权限: \dp - lists table/view permissions \dn+ - lists schema permissions \l+ does not list all users that can access the database using psql from postgres 8.4 and postgres 9.0, and the command \l or \l+ gives me column Access Privileges where I have entry: =c/ \dp显示的项解释如下: 角色名=xxxx -- 被授予给一个角色的特权 =xxxx -- 被授予给 PUBLIC 的特权 r -- SELECT ("读") w -- UPDATE ("写") a -- INSERT ("追加") d -- DELETE D -- TRUNCATE x -- REFERENCES t -- TRIGGER X -- EXECUTE U -- USAGE C -- CREATE c -- CONNECT T -- TEMPORARY arwdDxt -- ALL PRIVILEGES (对于表,对其他对象会变化) * -- 用于前述特权的授权选项 /yyyy -- 授予该特权的角色 在PostgreSQL中,可以把角色划分为如下几类: SELECT:该权限用来查询表或是表上的某些列,或是视图,序列。 INSERT:该权限允许对表或是视图进行插入数据操作,也可以使用COPY FROM进行数据的插入。 UPDATE:该权限允许对表或是或是表上特定的列或是视图进行更新操作。 DELETE:该权限允许对表或是视图进行删除数据的操作。 TRUNCATE:允许对表进行清空操作。 REFERENCES:允许给参照列和被参照列上创建外键约束。 TRIGGER:允许在表上创建触发器。 CREATE:对于数据库,允许在数据库上创建Schema;对于Schema,允许对Schema上创建数据库对象;对于表空间,允许把表或是索引指定到对应的表空间上。 CONNECT:允许用户连接到指定的数据库上。 TEMPORARY或是TEMP:允许在指定数据库的时候创建临时表。 EXECUTE:允许执行某个函数。 USAGE:对于程序语言来说,允许使用指定的程序语言创建函数;对于Schema来说,允许查找该Schema下的对象;对于序列来说,允许使用currval和nextval函数;对于外部封装器来说,允许使用外部封装器来创建外部服务器;对于外部服务器来说,允许创建外部表。 ALL PRIVILEGES:表示一次性给予可以授予的权限。 创建两个测试账号 create role web login connection limit 9 password 'web_app'; create role mobile login connection limit 9 password 'mob_ile'; ALTER DEFAULT PRIVILEGES IN SCHEMA dba GRANT SELECT ON TABLES TO mobile; 没有起到作用,用下面的语句: GRANT SELECT ON ALL TABLES IN SCHEMA dba TO mobile; 从dba终端看是有权限的,但mobile中用\dpp却看不到,难道要重新登录一下? 重新登录后也看不到,试试下面的规则: GRANT CONNECT ON DATABASE dba TO mobile; GRANT USAGE ON SCHEMA dba TO mobile; GRANT SELECT ON ALL TABLES IN SCHEMA dba TO mobile; GRANT SELECT ON ALL SEQUENCES IN SCHEMA dba to mobile; 单表授权 GRANT SELECT,INSERT,UPDATE ON TABLE web9 TO web; 成功。 后来发现是search_path这个变量的问题,在当前的变量中没有包含dba,所以\dpp时看不见,但从其中的表中取数据是可以的:select * from dba.table limit 9; If your read-only user doesn't have permission to list tables (i.e. \d returns no results), it's probably because you don't have USAGE permissions for the schema. USAGE is a permission that allows users to actually use the permissions they have been assigned. What's the point of this? I'm not sure. To fix: # You can either grant USAGE to everyone GRANT USAGE ON SCHEMA public TO public; # Or grant it just to your read only user GRANT USAGE ON SCHEMA public TO readonlyuser; 授权首先要能连接(connection)到数据库(pg_hba.conf)上,在模式上要有使用权限(usage),然后是其下的对象的操作权限(如果该对象可以再度分割,如表中有列,对列赋予不同的权限);可以对用户在给定的模式下设定权限(可批可零),或对给定的模式中指定默认的操作权限(批量)。 撤销权限 REVOKE CREATE ON SCHEMA public FROM public; 第一个 "public" 是模式,第二个 "public" 意思是"所有用户"。 GRANT SELECT ON ALL TABLES IN SCHEMA PUBLIC to freeoa_role; --赋予freeoa_role所有表的SELECT权限 特殊符号:ALL代表所访问权限,PUBLIC代表所有用户。 要把新的模式放到路径中来,我们用: SET search_path TO myschema,"$user",public; 仅对本次会话有效,下次登录又要设置一下。 或者修改用户的搜索路径,这样即使下次登录也不用重新设置: ALTER USER mobile SET search_path=dba, "$user",public; 修改模式默认的权限 alter default privileges in schema public grant select on tables to web; 比较通用的模式下对象授权方式多采用:先移除所有用户的所有权限,再有针对性的授权。 REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO user_name; 或者修改具体用户的默认权限 ALTER DEFAULT PRIVILEGES FOR ROLE some_role -- Alternatively "FOR USER" IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO user_name; 这是一个很开放的权限 grant all privileges on database dbname to dbuser; grant是赋予用户schema下当前表的权限,alter default privileges是赋予用户schema下表的默认权限,这样以后新建表就不用再赋权限了。当我们创建只读账号的时候,需要执行grant和alter default privileges。其次这样可很好地解决每次新建表就要赋一次权限的问题了。 alter default privileges in schema dba grant select,insert,update,delete on tables to mobile; 创建的普通用户默认是没有任何权限的。查看表等对象的权限可通过:\dpp来查看,相当直观。 序列的权限与解决办法 在insert的时候,指定列插入,主键id是serial类型会默认走sequence的下一个值,但前面只赋予了表的权限,所以会出现下面的问题: postgres=> insert into t4 ( name ) values ( 'aa' ); ERROR: permission denied for sequence t4_id_seq 解决方法就是再赋一次sequence的值就行了 alter default privileges in schema public grant usage on sequences to user2; 删除用户 删除用户和组 删除用户和组很简单: DROP ROLE role_name; DROP ROLE IF EXISTS role_name; 删除组role只会删除组的role本身,组的成员并不会被删除。 postgres=> \c - postgres You are now connected to database "postgres" as user "postgres". postgres=# drop role user2; ERROR: role "user2" cannot be dropped because some objects depend on it DETAIL: privileges for table t5 privileges for sequence t5_id_seq privileges for default privileges on new sequences belonging to role postgres in schema public privileges for table t4 privileges for default privileges on new relations belonging to role postgres in schema public 当我们删除用户的时候,会提示有权限依赖,所以我们要删除这些权限 postgres=# alter default privileges in schema public revoke usage on sequences from user2; ALTER DEFAULT PRIVILEGES postgres=# alter default privileges in schema public revoke select,insert,delete,update on tables from user2; ALTER DEFAULT PRIVILEGES postgres=# revoke select,insert,delete,update on all tables in schema public from user2; REVOKE postgres=# revoke usage on all sequences in schema public from user2; REVOKE postgres=# drop role user2; DROP ROLE Pg权限分为两部分,一部分是“系统权限”或者数据库用户的属性,可以授予role或user(两者区别在于login权限);一部分为数据库对象上的操作权限。对超级用户不做权限检查,其它走acl。对于数据库对象,开始只有所有者和超级用户可以做任何操作,其它走acl。在pg里,对acl模型做了简化,组和角色都是role。数据库对象上的权限有:SELECT,INSERT,UPDATE,DELETE,RULE,REFERENCES,TRIGGER,CREATE,TEMPORARY,EXECUTE 和 USAGE等。 可以用特殊的名字 PUBLIC 把对象的权限赋予系统中的所有角色。 在权限声明的位置上写 ALL,表示把适用于该对象的所有权限都赋予目标角色。 视图 pg_roles提供访问数据库角色有关信息的接口。 它只是一个 pg_authid 表的公开可读部分的视图,把口令字段用空白填充了。 pg_roles字段 名字 类型 引用 描述 rolname name 角色名 rolsuper bool 有超级用户权限的角色 rolcreaterole bool 可以创建更多角色的角色 rolcreatedb bool 可以创建数据库的角色 rolcatupdate bool 可以直接更新系统表的角色。(除非这个字段为真,否则超级用户也不能干这个事情。) rolcanlogin bool 可以登录的角色,也就是说,这个角色可以给予初始化会话认证的标识符。 rolpassword text 不是口令(总是 ********) rolvaliduntil timestamptz 口令失效日期(只用于口令认证);如果没有失效期,为 NULL rolconfig text[] 运行时配置变量的会话缺省 角色属性(Role Attributes) 一个数据库角色可以有一系列属性,这些属性定义了他的权限。 属性 说明 login 只有具有 LOGIN 属性的角色可以用做数据库连接的初始角色名。 superuser 数据库超级用户 createdb 创建数据库权限 createrole 允许其创建或删除其他普通的用户角色(超级用户除外) replication 做流复制的时候用到的一个用户属性,一般单独设定。 password 在登录时要求指定密码时才会起作用,比如md5或者password模式,跟客户端的连接认证方式有关 inherit 用户组对组员的一个继承标志,成员可以继承用户组的权限特性 在psql中的查看权限的快捷指令 \dn[S+] [PATTERN] 列出所有模式 \dp [模式] 列出表,视图和序列的访问权限,同\z \du[S+] [PATTERN] 列出角色 \ddp [模式] 列出默认权限 \drds [模式1 [模式2]] 列出每个数据库的角色设置 database、schema、table_seq_view_etc、table_column 分4个级别来授权。 查看pg_hba.conf 文件,在角色属性中关于password的说明,在登录时要求指定密码时才会起作用,比如md5或者password模式,跟客户端的连接认证方式有关。 给已存在用户赋权限 使用ALTER ROLE 命令。 ALTER ROLE name RENAME TO new_name ALTER ROLE name [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT } ALTER ROLE name [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT ALTER ROLE name [ IN DATABASE database_name ] RESET configuration_parameter ALTER ROLE name [ IN DATABASE database_name ] RESET ALL 为角色成员赋权 查看角色信息 psql 终端可以用\du 或\du+ 查看,也可以查看系统表 select * from pg_roles; select * from pg_user; 在系统的角色管理中,通常会把多个角色赋予一个组,这样在设置权限时只需给该组设置即可,撤销权限时也是从该组撤销。在PostgreSQL中,首先需要创建一个代表组的角色,之后再将该角色的membership 权限赋给独立的角色即可。 创建组角色 # CREATE ROLE father login nosuperuser nocreatedb nocreaterole noinherit encrypted password 'freeoa'; 给father 角色赋予数据库test 连接权限和相关表的查询权限。 # GRANT CONNECT ON DATABASE test to father; test=> GRANT USAGE ON SCHEMA public to father; WARNING: no privileges were granted for "public" test=> GRANT SELECT on public.emp to father; 创建成员角色 test=> \c postgres postgres You are now connected to database "postgres" as user "postgres". # CREATE ROLE son1 login nosuperuser nocreatedb nocreaterole inherit encrypted password 'freeoa.net'; 这里创建了son1 角色,并开启inherit 属性。PostgreSQL 里的角色赋权是通过角色继承(INHERIT)的方式实现的。 将father 角色赋给son1 # GRANT father to son1; 还有另一种方法,就是在创建用户的时候赋予角色权限。 # CREATE ROLE son2 login nosuperuser nocreatedb nocreaterole inherit encrypted password 'freeoa.net' in role father; 用户在public模式下创建的表对于其它用户能看到,但查不了,会报"对关系 prv 权限不够",除非你是这个库的属主。 可以通过函数来验证模式下的表的相应权限: select has_table_privilege('public.table1','select'); select has_table_privilege('dba.webcon_cid_seq','update'); 对sequence类型的授权 select 什么都做不了,usage有currval,nextval这两个函数可用,setval不可用,要使用setval就必须有update权限。 grant usage on sequence web_cid_seq to some_user; 切换ROLE SET ROLE role_name; --切换到role_name用户 RESET ROLE; --切换回最初的role INHERIT权限:该属性使组成员拥有组的所有权限 ALTER ROLE freeoa_user INHERIT; 通过以下方式禁止用户登录 ALTER ROLE username WITH NOLOGIN; 第三方的小工具 somebody created a convenient script for that; pg_grant_read_to_db.sh. This script grants read-only privileges to a specified role on all tables, views and sequences in a database schema and sets them as default. url:https://gist.github.com/jirutka/afa3ce62b1430abf7572 参考来源 GRANT[http://postgres.cn/docs/9.5/sql-grant.html] ALTER DEFAULT PRIVILEGES[http://postgres.cn/docs/9.5/sql-alterdefaultprivileges.html]