Oracle 12c用戶和安全管理


前言:

Oracle 12c的多租戶(multitenant)環境與SQL Server的架構非常相似,CDB$ROOT類似於master、PDB$SEED類似於model、各個pluggable database就相當於普通的業務庫。
官方宣傳了12c的很多好處但其實沒卵用,12c設想通過合並多個庫來避免DBLINK的性能問題,但其實還是通過壓榨單一服務器來實現的,其他好處諸如PDB遷移方便、JSON支持、資源組、索引壓縮、in-memory支持等等要么是炒冷飯,要么實際適用場景很少,不過這些新特性都還有待繼續研究,一步一步來。
首先必須要解決的是登錄問題,12c的多租戶環境下用戶與以前不同了,以前的用戶性質都是一樣的,而在12c中一個實例下可以有多個可插拔的數據庫,因此用戶管理與之前就有很大區別了,本文介紹12c用戶及其管理,以12.2.0.1版本為例,所有觀點來源於如下官網鏈接:
本文主要包含以下六個部分:
  • 關於用戶安全的簡易說明
  • 創建用戶
  • 更改用戶
  • 配置用戶資源限額
  • 刪除用戶
  • 用戶和profile的的數據字典
一、關於用戶安全的簡易說明:

每個數據庫都有自己的用戶列表,在創建用戶時你可以為這個用戶設置一系列的登錄limits或resource limits,或者使用profile實現此功能,profile就是一個用戶所擁有的屬性的集合,你可以查看dba_profiles來詳細了解。
此外你還可以為用戶賦予一系列的權限和角色,參考:Configuring Privilege and Role Authorization
 
二、創建用戶

這部分涉及的內容很多,保險起見還是全部列出來的比較好。
  • 關於Common User和Local User
在多租戶的環境中,common user可以訪問整個CDB而local user只能訪問特定的PDB,關於CDB與PDB的關系這里用官網的一幅圖來表示:

可以看到CDB其實就是指實例下的所有數據庫,包含ROOT、Seed和其他所有PDBs,整個Instance可以看做一個容器,即Container DB(CDB).

你可以使用sysdba用戶來啟動PDB,有以下兩種方式:
1.alter session set container=orclpdb1;
  alter database open;
  --對應關閉方式為shutdown immediate;
2.alter pluggable database orclpdb1 open;
  --對應關閉方式為alter pluggable database orclpdb1 close;
Ps:PDB的關閉是指將PDB由open變為mount狀態,徹底shutdown需要到root中關閉整個實例。

關於Common user:

Common user必須以C##或者c##開頭,你可以通過修改common_user_prefix參數來更改這個prefix,而Local user則必須避免以這個prefix開頭。
Common user的身份和密碼對於每個PDB來說都是可見的,只要有合適的權限common user也可以操作PDB。
Common user通常用於在root中操作PDBs,例如插拔PDB數據庫、更改PDB狀態或者為CDB指定臨時表空間等。
Common user只能在cdb$root中創建,cdb$root中也只能創建common user。
舉例來講,common user可做的操作有:創建或修改common/local user、向其他common/local user賦權限或者賦角色、對整個CDB執行ALTER DATABASE開頭的恢復語句、通過ALTER PLUGGABLE DATABASE語句來來更改PDB的狀態(必須是連接到CDB$ROOT庫時)。當然一個local user如果有權限也可以更改其自身PDB的狀態。
Oracle的系統用戶如sys、system等,就是common user,即可操作ROOT數據庫也可以操作任意PDB,除非某個PDB開啟Vault-enabled來限制系統用戶的權限。

當你將一個non-CDB的數據庫作為PDB插入到CDB中時:

  1. non-CDB的系統用戶將會與CDB common user合並,即non-CDB中的系統用戶將會新增到CDB中,如果username沖突則不新增,這些沖突系統用戶的密碼全部按照CDB的來,原密碼失效。
  2. 如果你曾經更改過原non-CDB系統用戶的權限,那么合並之后這些差異權限只對這個PDB生效,對其他PDB無效。這里還不知道如果少了權限合並之后是不是依然少,有需要的時候再測試下好了。
當你將一個PDB插入CDB時:
  1. 原PDB的common user會失去它所有的公共權限,包括set container的權限。
  2. 如果目標CDB有與PDB同名的common user,那么這兩個common user合並,CDB的common user密碼優先生效。而PDB中其他不同名的common user將會被鎖定。你可以對這些鎖定的common user做如下任意一種處理:
    • 不處理這些locked用戶,在權限適當的情況下你依然可以使用這些schema下的對象。
    • 使用EXPDP導出這些用戶下的數據並導入到另一個用戶下,然后刪掉此locked user。
    • 關掉PDB,連接到CDB$ROOT,創建同名的common user,然后重開PDB,Oracle會自動處理權限差異,此時你可以unlock這些用戶,他們的本地權限保持不變。
關於Local user:
Local user就是只存在於PDB中的用戶,local user可以擁有管理類權限,但是這類權限只對local user所在的PDB有效。
Local user與common user的區別可以概括為以下幾點:
  1. Local user不能創建common user,也不能在cdb$root中被授予權限。而common user只要有合適的權限,就能創建、修改common/local user,就能公共的或本地的grant/revoke權限。Local user如果權限充足,可以創建、修改local user,也可以在PDB中向common/local user賦權限。
  2. 你可以向local user賦予公共角色或權限(類似於select any table這種),但是這些公共角色或權限包含的權限只對其所屬PDB有效。
  3. Local user在一個PDB中應當是唯一的。
  4. 如果local user有合適的權限,那么它也可以訪問common user里的對象。
  5. Local user只能在PDB中被創建,PDB中也只能創建local user而不能創建common user。
  6. 你可以根據版本來選擇是否禁用local user,但是卻不能這么操作common user。
  • 創建用戶示例
創建common user:
$ sqlplus / as sysdba
SQL> show pdbs;
    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 ORCLPDB1			  READ WRITE NO
	 4 ORCLPDB2			  MOUNTED
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL> alter pluggable database orclpdb1 open;
Pluggable database altered.
SQL> create user c##test identified by test container=all;  
--common user只能以c##開頭,且強制container=all,創建時可以不用寫container=all。
SQL> grant dba to c##test;
--至此common user c##test創建完畢,但是目前為止這個common user只能操作CDB$ROOT schema對象下的objects和創建PDB的local user,並沒有操作PDB下objects的權限,一般來說common user不必有此權限,但是如果你想擁有,那么:
SQL> alter session set container=orclpdb1;  --切換至orclpdb1的PDB后再次grant權限
SQL> grant dba to c##test;
--至此common user c##test就擁有了操作PDB orclpdb1下objects的權限了。但是這種common user刪除時必須添加cascade:
SQL> drop user c##test;
drop user c##test
*
ERROR at line 1:
ORA-65048: error encountered when processing the current DDL statement in pluggable database ORCLPDB1
ORA-01922: CASCADE must be specified to drop 'C##TEST'
SQL> drop user c##test cascade;
User dropped.

創建local user:

$ sqlplus / as sysdba
SQL> alter session set container=orclpdb1;
SQL> create user test identified by test default tablespace users quota 100M on example quota 200M on test temporary tablespace temp profile default container=current;
--local user只能以非c##開頭,且強制container=current,創建時可以不用寫container=current。
SQL> grant connect,resource,unlimited tablespace to test;
$ sqlplus test/test@localhost/orclpdb1
--至此local user創建完畢。
--需要特別注意的一點是:12c的resource角色中已經不包含unlimited tablespace權限因此需要單獨賦予,或者通過quota項來分配一定的表空間限額。
  • 創建用戶總結:
一般來說沒有必要創建除系統用以外的common user,或者只需要創建一個不含操作具體PDB權限的common user,common user不應當用於操作具體業務數據,正如官方說明的那樣,common user通常的操作應當是:
   創建或修改common/local user、向其他common/local user賦權限或者賦角色、對整個CDB執行ALTER DATABASE開頭的恢復語句、通過ALTER PLUGGABLE DATABASE語句來來更改PDB的狀態(必須是連接到CDB$ROOT庫時)。
我們可以使用如下SQL來查看PDB或CDB$ROOT庫內的用戶:
$ sqlplus / as sysdba
SQL> alter session set container=orclpdb1;
SQL> set lines 200
SQL> set pages 100
SQL> col username for a40
SQL> select USERNAME,ACCOUNT_STATUS,COMMON from dba_users;
--結果可以看到common user是在所有PDB中可見的,在單個PDB中查詢dba_users你能看到所有common user和屬於本PDB的local user。

再來考慮一種特殊情況,假如我們需要在一個PDB中訪問另一個PDB中的數據呢?
使用local user是不可能的,因為local user完全PDB隔離,就算local user被賦予了類似dba、select any table這些公共權限,也只是在PDB內有效,無法跨庫訪問,那么只能使用common user。

接下來舉例common user跨PDBs訪問:

SQL> show pdbs;
    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
	 2 PDB$SEED			  READ ONLY  NO
	 3 ORCLPDB1			  READ WRITE NO
	 4 ORCLPDB2			  READ WRITE NO
--我們有兩個PDB:orclpdb1和orclpdb2都是open狀態,各自有一個scott用戶,用戶下分別有一個test1、test2表。我們先創建一個common user:
$ sqlplus / as sysdba
SQL> create user c##scott identified by tiger;
SQL> grant connect,resource,unlimited tablespace,select any table,create view to c##scott;
--然后在orclpdb1中給c##scott賦權限
SQL> alter session set container=orclpdb1;
SQL> grant connect,resource,unlimited tablespace,select any table,create view to c##scott;
--接下來在orclpdb2中給c##scott賦權限
SQL> alter session set container=orclpdb2;
SQL> grant connect,resource,unlimited tablespace,select any table,create view to c##scott;

至此c##scott用戶就有了在兩個pdb中查詢的權限,但是此權限是嚴格PDB隔離的,不能跨庫查詢。雖然不能像SQL Server那樣跨庫直接查詢,不過oracle卻提供了變通的辦法--CONTAINERS子句,參考網址如下(此特性開始於12.1.0.2版本):

舉例: SELECT ename FROM CONTAINERS(scott.emp) WHERE CON_ID IN (45, 49);

想要使用CONTAINERS子句必須滿足以下條件:

1.CONTAINERS子句中的表、視圖或同義詞必須在ROOT和所有PDB中都存在。
2.CONTAINERS子句中涉及的表、視圖的屬主必須是執行SQL語句的common user;如果是同義詞,那么這個同義詞必須是引用的此common user下的表或視圖。
3.包含CONTAINERS子句的SQL必須在CDB$ROOT數據庫下使用common user執行。

如果CONTAINERS子句涉及的表里有以下列類型,那么會被自動過濾掉:

1.用戶定義的類型:object types, varrays, REFs, and nested tables
2.系統類型:ANYTYPE, ANYDATASET, URI types, SDO_TOPO_GEOMETRY, SDO_GEORASTER, and Expression
看完以上5條要求后突然發現這些要求很奇葩,如果CONTAINERS子句中的表、視圖或同義詞必須在ROOT和所有PDB中都存在,那我還為什么還要跨PDB查詢,直接在ROOT中查不就得了?

稍微思考和實踐了一下,發現使用CONTAINERS子句的條件應該是:

  • 必須使用common user在CDB$ROOT中查詢
  • CONTAINERS()方法的輸入是表、視圖或同義詞,這個對象必須在CDB$ROOT中有個名稱+結構完全相同的對象,無論是表還是視圖還是同義詞,表可以沒有數據。
  • 必須使用執行此查詢的common user到表所在的PDB中創建一個同名view,這需要common user擁有查詢此表的權限。

那么接着上邊的實例就可以很容易的進行跨PDB查詢了:

1.首先我們使用common user c##scott在orclpdb1中創建針對scott.test1的視圖:
$ sqlplus c##scott/tiger@orclpdb1
SQL> create view test1 as select * from scott.test1;
2.然后使用common user c##scott在CDB$ROOT中創建同名的表或者視圖:
$ sqlplus c##scott/tiger
SQL> create table test1(name varchar2(20));
3.此時我們就可以使用SQL查詢了:
SQL> select * from CONTAINERS(test1) where con_id=3;
4.如果還需要聯結查詢orclpdb2中的test2表,那么:
$ sqlplus c##scott/tiger@orclpdb2
SQL> create view test2 as select * from scott.test2;
$ sqlplus c##scott/tiger
SQL> create table test2(name varchar2(20));
5.這樣就相當於test1和test2在CDB$ROOT中都有了一個接口,我們通過接口訪問相應PDB中的common user下的視圖,視圖又是直接定義在最終表上的。
 
畫一幅圖來直觀的表示:

 

三、修改用戶

修改用戶與創建用戶的語法很相似:
--一個官方示例:
ALTER USER c##hr_admin
 DEFAULT TABLESPACE data_ts
 TEMPORARY TABLESPACE temp_ts
 QUOTA 100M ON data_ts
 QUOTA 0 ON test_ts
 SET CONTAINER_DATA = (emp_db, hr_db) FOR V$SESSION 
 CONTAINER = CURRENT;
 --有以下幾個地方需要解釋:
 1.QUOTA的大小表示在表空間上限額的總大小,而非增/減量。
 2.SET CONTAINER_DATA表示此common user在root中訪問v$session時可以獲取到emp_db和hr_db相關的session信息。

此外一般用戶的密碼可以通過alter user語句修改,而sys密碼可以通過orapwd工具修改:

orapwd file='orapworcl' force=y
orapwd input_file='orapworcl' file='orapwd' sys=y force=y
 
四、配置用戶資源限額

這點可以通過一個視圖很容易的看到:

因此修改用戶資源限額就很簡單了,例如:
alter user scott limit password_life_time unlimited;
--或者新建一個profile,然后將其指定為用戶的profile:
CREATE PROFILE profile_scott LIMIT
  FAILED_LOGIN_ATTEMPTS 6
  PASSWORD_LIFE_TIME 60
  PASSWORD_REUSE_TIME 60
  PASSWORD_REUSE_MAX 5
  PASSWORD_LOCK_TIME 1/24
  PASSWORD_GRACE_TIME 10
  PASSWORD_VERIFY_FUNCTION DEFAULT;
alter user scott profile profile_scott; 

五、刪除用戶


六、用戶和profile涉及的數據字典

ALL_OBJECTS
Describes all objects accessible to the current user
ALL_USERS
Lists users visible to the current user, but does not describe them
DBA_PROFILES
Displays all profiles and their limits
DBA_TS_QUOTAS
Describes tablespace quotas for users
DBA_OBJECTS
Describes all objects in the database
DBA_USERS
Describes all users of the database
DBA_USERS_WITH_DEFPWD
Lists all user accounts that have default passwords
PROXY_USERS
Describes users who can assume the identity of other users
RESOURCE_COST
Lists the cost for each resource in terms of CPUs for each session, reads for each session, connection times, and SGA
USER_PASSWORD_LIMITS
Describes the password profile parameters that are assigned to the user
USER_RESOURCE_LIMITS
Displays the resource limits for the current user
USER_TS_QUOTAS
Describes tablespace quotas for users
USER_OBJECTS
Describes all objects owned by the current user
USER_USERS
Describes only the current user
V$SESSION
Lists session information for the current database session
V$SESSTAT
Displays user session statistics
V$STATNAME
Displays decoded statistic names for the statistics shown in the V$SESSTAT view


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM