1. 程式人生 > 其它 >ORACLE如何檢視當前賬號的相關資訊總結

ORACLE如何檢視當前賬號的相關資訊總結

關於Oracle資料庫的賬號,我們在維護資料庫的時候,偶爾可能需要獲取一些特殊資訊。例如,賬號的建立時間、賬號的狀態、賬號的鎖定時間.....。正常情況下,我們可以通過DBA_USERS獲取大部分相關資訊。但是有一些特殊資訊,還必須通過不常用底層基表sys.user$來獲取。

SQL> DESC DBA_USERS;
 Name Null? Type
 ----------------------------------------- -------- ----------------------------
 USERNAME NOT NULL VARCHAR2(30)
 USER_ID NOT
NULL NUMBER
 PASSWORD VARCHAR2(30)
 ACCOUNT_STATUS NOTNULL VARCHAR2(32)
 LOCK_DATE DATE
 EXPIRY_DATE DATE
 DEFAULT_TABLESPACE NOTNULL VARCHAR2(30)
 TEMPORARY_TABLESPACE NOTNULL VARCHAR2(30)
 CREATED NOTNULLDATE
 PROFILE NOTNULL VARCHAR2(30)
 INITIAL_RSRC_CONSUMER_GROUP VARCHAR2(30)
 EXTERNAL_NAME VARCHAR2(4000)

其實我們經常使用的DBA_USERS是同義詞,對應SYS.DBA_USERS這個檢視。如果你想檢視SYS.DBA_USERS的定義,可以通過下面方式:

--ORACLE 10g
SQL>SELECT DBMS_METADATA.GET_DDL('VIEW', 'DBA_USERS', 'SYS') FROM DUAL;
CREATEOR REPLACE FORCE VIEW "SYS"."DBA_USERS" (
 "USERNAME"
, "USER_ID"
, "PASSWORD"
, "ACCOUNT_STATUS"
, "LOCK_DATE"
, "EXPIRY_DATE"
, "DEFAULT_TABLESPACE"
, "TEMPORARY_TABLESPACE"
, "CREATED"
, "PROFILE"
, "INITIAL_RSRC_CONSUMER_GROUP"
, "EXTERNAL_NAME") AS
 select u.name, u.user#, u.password,
 m.status,
 decode(u.astatus, 4, u.ltime,
 5, u.ltime,
 6, u.ltime,
 8, u.ltime,
 9, u.ltime,
 10, u.ltime, to_date(NULL)),
 decode(u.astatus,
 1, u.exptime,
 2, u.exptime,
 5, u.exptime,
 6, u.exptime,
 9, u.exptime,
 10, u.exptime,
 decode(u.ptime, '', to_date(NULL),
 decode(pr.limit#, 2147483647, to_date(NULL),
 decode(pr.limit#, 0,
 decode(dp.limit#, 2147483647, to_date(NULL), u.ptime +
 dp.limit#/86400),
 u.ptime + pr.limit#/86400)))),
 dts.name, tts.name, u.ctime, p.name,
 nvl(cgm.consumer_group, 'DEFAULT_CONSUMER_GROUP'),
 u.ext_username
 from sys.user$ u leftouterjoin sys.resource_group_mapping$ cgm
 on (cgm.attribute = 'ORACLE_USER'and cgm.status = 'ACTIVE'and
 cgm.value = u.name),
 sys.ts$ dts, sys.ts$ tts, sys.profname$ p,
 sys.user_astatus_map m, sys.profile$ pr, sys.profile$ dp
 where u.datats# = dts.ts#
 and u.resource$ = p.profile#
 and u.tempts# = tts.ts#
 and u.astatus = m.status#
 and u.type# = 1
 and u.resource$ = pr.profile#
 and dp.profile# = 0
 and dp.type#=1
 and dp.resource#=1
 and pr.type# = 1
 and pr.resource# = 1

通過上面的檢視定義,我們可以知道,大部分資料來自於底層基表sys.user$。關於表sys.user$的結構如下,我們可以從sql.bsq中可以看到sys.user$的定義。

SQL> DESC sys.user$
 Name Null? Type
 ----------------------------------------- -------- ----------------------------
 USER# NOT NULL NUMBER
 NAME NOTNULL VARCHAR2(30) 
 TYPE# NOTNULL NUMBER
 PASSWORD VARCHAR2(30)
 DATATS# NOTNULL NUMBER
 TEMPTS# NOTNULL NUMBER
 CTIME NOTNULLDATE
 PTIME DATE
 EXPTIME DATE
 LTIME DATE
 RESOURCE$ NOTNULL NUMBER
 AUDIT$ VARCHAR2(38)
 DEFROLE NOTNULL NUMBER
 DEFGRP# NUMBER
 DEFGRP_SEQ# NUMBER
 ASTATUS NOTNULL NUMBER
 LCOUNT NOTNULL NUMBER
 DEFSCHCLASS VARCHAR2(30)
 EXT_USERNAME VARCHAR2(4000)
 SPARE1 NUMBER
 SPARE2 NUMBER
 SPARE3 NUMBER
 SPARE4 VARCHAR2(1000)
 SPARE5 VARCHAR2(1000)
 SPARE6 DATE

其中,我們可以獲取一下關鍵欄位資訊,具體如下

NAME 使用者(User)或角色(Role)的名字 
TYPE# 0表示Role,1表示User
CTIME 使用者的建立時間
PTIME 密碼最後一次修改時間
EXPTIME 密碼過期的時間
LTIME 賬號最後一次鎖定的時間
LCOUNT 使用者登入失敗次數。

下面我們簡單測試驗證一下,

SQL> CREATEUSER TEST IDENTIFIED BY "Test#1232134$#3" DEFAULT TABLESPACE TBS_TEST_DATA TEMPORARY TABLESPACE TEMP;
User created.
SQL> GRANTCONNECTTO TEST;
SQL> @get_user_info.sql
Session altered.
Enter valuefor user_name: TEST
old 9: WHERE NAME=('&USER_NAME')
new 9: WHERE NAME=('TEST')
NAME TYPE# CTIME PTIME EXPTIME LTIME LCOUNT
------------------------------ ---------- ------------------- ------------------- ------------------- ------------------- ----------
TEST 1 2021-06-10 14:10:01 2021-06-10 14:10:01 0
SQL> ALTERUSER TEST IDENTIFIED BY "kER124";
User altered.
SQL> @get_user_info.sql
Session altered.
Enter valuefor user_name: TEST
old 9: WHERE NAME=('&USER_NAME')
new 9: WHERE NAME=('TEST')
NAME TYPE# CTIME PTIME EXPTIME LTIME LCOUNT
------------------------------ ---------- ------------------- ------------------- ------------------- ------------------- ----------
TEST 1 2021-06-10 14:10:01 2021-06-10 14:10:50 0
SQL> ALTERUSER TEST ACCOUNT LOCK;
User altered.
SQL> @get_user_info.sql
Session altered.
Enter valuefor user_name: TEST
old 9: WHERE NAME=('&USER_NAME')
new 9: WHERE NAME=('TEST')
NAME TYPE# CTIME PTIME EXPTIME LTIME LCOUNT
------------------------------ ---------- ------------------- ------------------- ------------------- ------------------- ----------
TEST 1 2021-06-10 14:10:01 2021-06-10 14:10:50 2021-06-10 14:11:27 0
SQL> 

其中get_user_info.sql的指令碼如下

$ more get_user_info.sql
ALTERSESSIONSET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS';
SELECT NAME
 , TYPE#
 , CTIME
 , PTIME
 , EXPTIME
 , LTIME
 , LCOUNT
FROMuser$
WHERE NAME=('&USER_NAME');

另外,我們來測試一下賬號登入失敗次數,在實驗前先解鎖賬號,用錯誤的賬號密碼嘗試登入資料庫,你會發現LCOUNT就變成1了。

SQL> @get_user_info.sql
Session altered.
Enter valuefor user_name: TEST
old 9: WHERE NAME=('&USER_NAME')
new 9: WHERE NAME=('TEST')
NAME TYPE# CTIME PTIME EXPTIME LTIME LCOUNT
------------------------------ ---------- ------------------- ------------------- ------------------- ------------------- ----------
TEST 1 2021-06-10 14:10:01 2021-06-10 14:10:50 2021-06-10 14:11:27 1
SQL> 

那麼這個LCOUNT欄位的值是一直累加到超過閾值鎖定呢?還是中間會清零呢?什麼情況下會清零呢? 如果你使用正確的密碼成功登入資料庫後,你會發現LCOUNT的值就清零了。如下截圖所示:

$ sqlplus /nolog
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Jun 10 14:30:41 2021
Copyright (c) 1982, 2007, Oracle. All Rights Reserved.
SQL> connect TEST
Enter password: 
Connected.

也就是說,只要你在鎖定之前,一旦成功登入之後,該計數會被清零。在有些版本中,由於Bug,也會出現LCOUNT沒有正確反映登入失敗次數的情況,例如Lcount neither reset on correct login nor incremented after incorrect login thru JDBC (Doc ID 2675398.1)中記錄了這樣的案例。另外,ORACLE 12C 後新增了一個功能,它會記錄使用者的最後一次登入時間:SPARE6欄位記錄使用者的最後一次登入時間

參考資料

https://www.eygle.com/archives/2009/07/profile_failed_login_attempts.html

https://dbaora.com/sys-user-table-in-oracle-last-password-change-time-last-locked-last-expired-creation-time-failed-logon/

Lcount neither reset on correct login nor incremented after incorrect login thru JDBC (Doc ID 2675398.1)

https://bijoos.com/oraclenotes/2013/153/