【PROFILE】使用Oracle的PROFILE對使用者資源限制和密碼限制的研究與探索

路途中的人2012發表於2016-02-27
1.使用者建立語句PROFILE選項“引發的血案”
如果大家細心的話,在建立使用者的語法中有這麼一個選項“PROFILE profile”。
下面是Oracle 11gR2官方文件中關於建立使用者的語法描述(較之10g的文件可讀性加強了,當然功能也同樣有所增加):
CREATE USER user
   IDENTIFIED { BY password
              | EXTERNALLY [ AS 'certificate_DN'  |  AS 'kerberos_principal_name' ]
              | GLOBALLY [ AS '[ directory_DN ]' ]
              }
   [ DEFAULT TABLESPACE tablespace
   | TEMPORARY TABLESPACE
        { tablespace | tablespace_group_name }
   | { QUOTA { size_clause | UNLIMITED } ON tablespace }...
   | PROFILE profile
   | PASSWORD EXPIRE
   | ACCOUNT { LOCK | UNLOCK }
     [ DEFAULT TABLESPACE tablespace
     | TEMPORARY TABLESPACE
          { tablespace | tablespace_group_name }
     | { QUOTA { size_clause | UNLIMITED } ON tablespace }...
     | PROFILE profile
     | PASSWORD EXPIRE
     | ACCOUNT { LOCK | UNLOCK }
     | ENABLE EDITIONS
     ]...
  ] ;


2.提問:PROFILE選項是做什麼用的呢?
回答:簡要的說,PROFILE在Oracle資料庫對資料庫使用者能夠使用的資源做進一步的限制的一種手段,如對連線到某個使用者的session或sql所能使用的CPU資源進行控制,又如控制Oracle使用者的密碼管理策略等等……

3.檢視系統的預設PROFILE
1)透過dba_profiles檢視檢視一下系統中預設都有哪些PROFILE
資料庫建立以後,系統中只會存在一個名為DEFAULT的預設PROFILE,在使用者建立之後,如果不做特殊指定,每個使用者的PROFILE都會預設的使用個預設的PROFILE。
sys@ora10g> select distinct profile from dba_profiles;

PROFILE
----------
DEFAULT

2)全面檢視一下這個PROFILE都包含哪些限制定義
sys@ora10g> select * from dba_profiles;

PROFILE    RESOURCE_NAME                    RESOURCE LIMIT
---------- -------------------------------- -------- -----------------
DEFAULT    COMPOSITE_LIMIT                  KERNEL   UNLIMITED
DEFAULT    SESSIONS_PER_USER                KERNEL   UNLIMITED
DEFAULT    CPU_PER_SESSION                  KERNEL   UNLIMITED
DEFAULT    CPU_PER_CALL                     KERNEL   UNLIMITED
DEFAULT    LOGICAL_READS_PER_SESSION        KERNEL   UNLIMITED
DEFAULT    LOGICAL_READS_PER_CALL           KERNEL   UNLIMITED
DEFAULT    IDLE_TIME                        KERNEL   UNLIMITED
DEFAULT    CONNECT_TIME                     KERNEL   UNLIMITED
DEFAULT    PRIVATE_SGA                      KERNEL   UNLIMITED
DEFAULT    FAILED_LOGIN_ATTEMPTS            PASSWORD 10
DEFAULT    PASSWORD_LIFE_TIME               PASSWORD UNLIMITED
DEFAULT    PASSWORD_REUSE_TIME              PASSWORD UNLIMITED
DEFAULT    PASSWORD_REUSE_MAX               PASSWORD UNLIMITED
DEFAULT    PASSWORD_VERIFY_FUNCTION         PASSWORD NULL
DEFAULT    PASSWORD_LOCK_TIME               PASSWORD UNLIMITED
DEFAULT    PASSWORD_GRACE_TIME              PASSWORD UNLIMITED

16 rows selected.

3)結論
透過上面的檢視,可以得到這個系統預設的PROFILE “DEFAULT”的配置資訊只對密碼的錯誤嘗試次數做了限制(最多可以錯誤輸錯10次密碼),如果我們啟用了PROFILE(下面有介紹如何啟用和停止PROFILE),預設的限制只有這些。如果想要改變限制條件,有兩種方法:第一種方法是可以對這個預設的PROFILE做個性化的調整;第二種方法是再重新定製一個新的PROFILE滿足新的需求。

4.對建立PROFILE的標準語法做一下“解剖麻雀”(更多細節可以參考Oracle的官方文件)
1)建立PROFILE的語法如下:
CREATE PROFILE profile
   LIMIT { resource_parameters 對資源的限制
         | password_parameters 對密碼的限制
         }...
;

2)對資料庫資源做限制時,下面是全部可用的引數:
{ { SESSIONS_PER_USER 每個使用者名稱所允許的並行會話數
  | CPU_PER_SESSION   一個會話一共可以使用的CPU時間,單位是百分之一秒
  | CPU_PER_CALL      一次SQL呼叫(解析、執行和獲取)允許使用的CPU時間
  | CONNECT_TIME      限制會話連線時間,單位是分鐘
  | IDLE_TIME         允許空閒會話的時間,單位是分鐘
  | LOGICAL_READS_PER_SESSION 限制會話對資料塊的讀取,單位是塊
  | LOGICAL_READS_PER_CALL    限制SQL呼叫對資料塊的讀取,單位是塊
  | COMPOSITE_LIMIT   “組合打法”
  }
  { integer | UNLIMITED | DEFAULT }
| PRIVATE_SGA   限制會話在SGA中Shared Pool中私有空間的分配
  { size_clause | UNLIMITED | DEFAULT }
}

3)對密碼做限制時,下面是全部可用的引數:
{ { FAILED_LOGIN_ATTEMPTS 帳戶被鎖定之前可以錯誤嘗試的次數
  | PASSWORD_LIFE_TIME    密碼可以被使用的天數,單位是天,預設值180天
  | PASSWORD_REUSE_TIME   密碼可重用的間隔時間(結合PASSWORD_REUSE_MAX)
  | PASSWORD_REUSE_MAX    密碼的最大改變次數(結合PASSWORD_REUSE_TIME)
  | PASSWORD_LOCK_TIME    超過錯誤嘗試次數後,使用者被鎖定的天數,預設1天
  | PASSWORD_GRACE_TIME   當密碼過期之後還有多少天可以使用原密碼
  }
  { expr | UNLIMITED | DEFAULT }
| PASSWORD_VERIFY_FUNCTION
  { function | NULL | DEFAULT }
}

5.OK,語法已經瞭然於胸,那麼我們來實際建立一個PROFILE(這裡的名字我們稱其為:sec_profile),在感性認識的同時一同探索一下在這個過程中會遇到的一些有趣現象。
1)嘗試建立一個混合型的PROFILE(包含資源限制和密碼限制)
sys@ora10g> CREATE PROFILE sec_profile LIMIT
  2     SESSIONS_PER_USER          UNLIMITED
  3     CPU_PER_SESSION            UNLIMITED
  4     CPU_PER_CALL               6000
  5     CONNECT_TIME               60
  6     LOGICAL_READS_PER_SESSION  DEFAULT
  7     LOGICAL_READS_PER_CALL     6000
  8     COMPOSITE_LIMIT            6000000
  9     PRIVATE_SGA                66K
 10     FAILED_LOGIN_ATTEMPTS      6
 11     PASSWORD_LIFE_TIME         60
 12     PASSWORD_REUSE_TIME        60
 13     PASSWORD_REUSE_MAX         5
 14     PASSWORD_LOCK_TIME         1/24
 15     PASSWORD_GRACE_TIME        10   
 16     PASSWORD_VERIFY_FUNCTION   verify_function
 17  /
CREATE PROFILE sec_profile LIMIT
*
ERROR at line 1:
ORA-07443: function VERIFY_FUNCTION not found

2)報錯原因
為什麼會報錯?錯誤提示很清楚,VERIFY_FUNCTION這個函式不存在。既然知道不存在,那我們如何建立它呢?
回答:
VERIFY_FUNCTION函式是透過utlpwdmg.sql指令碼建立的,該指令碼所在的目錄是$ORACLE_HOME/rdbms/admin/

3)建立密碼複雜性檢驗函式VERIFY_FUNCTION
我們使用utlpwdmg.sql指令碼建立以下這個VERIFY_FUNCTION密碼複雜度校驗函式
sys@ora10g> @?/rdbms/admin/utlpwdmg.sql

Function created.


Profile altered.

4)utlpwdmg.sql指令碼中的小秘密
細心的您在執行utlpwdmg.sql指令碼的過程中一定發現了有一個“Profile altered”的提示,難道這個指令碼修改了某個PROFILE資訊麼?正如您所料,它修改了系統的預設PROFILE “DEFAULT”,再次檢視一下現在的DEFAULT的定義資訊:
sys@ora10g> select * from dba_profiles;

PROFILE    RESOURCE_NAME                    RESOURCE LIMIT
---------- -------------------------------- -------- -----------------
DEFAULT    COMPOSITE_LIMIT                  KERNEL   UNLIMITED
DEFAULT    SESSIONS_PER_USER                KERNEL   UNLIMITED
DEFAULT    CPU_PER_SESSION                  KERNEL   UNLIMITED
DEFAULT    CPU_PER_CALL                     KERNEL   UNLIMITED
DEFAULT    LOGICAL_READS_PER_SESSION        KERNEL   UNLIMITED
DEFAULT    LOGICAL_READS_PER_CALL           KERNEL   UNLIMITED
DEFAULT    IDLE_TIME                        KERNEL   UNLIMITED
DEFAULT    CONNECT_TIME                     KERNEL   UNLIMITED
DEFAULT    PRIVATE_SGA                      KERNEL   UNLIMITED
DEFAULT    FAILED_LOGIN_ATTEMPTS            PASSWORD 3
DEFAULT    PASSWORD_LIFE_TIME               PASSWORD 60
DEFAULT    PASSWORD_REUSE_TIME              PASSWORD 1800
DEFAULT    PASSWORD_REUSE_MAX               PASSWORD UNLIMITED
DEFAULT    PASSWORD_VERIFY_FUNCTION         PASSWORD VERIFY_FUNCTION
DEFAULT    PASSWORD_LOCK_TIME               PASSWORD .0006
DEFAULT    PASSWORD_GRACE_TIME              PASSWORD 10

16 rows selected.

與系統建立時的DEFAULT PROFILE相比較,之前只有10次密碼輸入錯誤的限制,執行完成這個函式建立之後,我們發現系統預設的PROFILE已經對系統有了一個非常嚴格的約束。也就是說現在系統上的每一個使用者在預設情況下都多了這些密碼方面的限制。

5)驗證一下新預設的PROFILE “DEFAULT”關於錯誤密碼輸入次數的限制
我們模擬一下錯誤輸錯密碼三次後的效果,可以看到,在第四次輸入後,sec使用者被鎖定了。
sys@ora10g> conn sec/a
ERROR:
ORA-01017: invalid username/password; logon denied


Warning: You are no longer connected to ORACLE.
sys@ora10g> conn sec/a
ERROR:
ORA-01017: invalid username/password; logon denied


sys@ora10g> conn sec/a
ERROR:
ORA-01017: invalid username/password; logon denied


sys@ora10g> conn sec/a
ERROR:
ORA-28000: the account is locked

6)使用dba_users檢視比較一下使用者的前後狀態
使用者sec已經因錯誤密碼輸入次數超過3此導致使用者被鎖定了,進一步比較一下使用者的狀態。
sys@ora10g> col USERNAME for a10
sys@ora10g> col ACCOUNT_STATUS for a20
sys@ora10g> col PROFILE for a10
sys@ora10g> select USERNAME,ACCOUNT_STATUS,LOCK_DATE,EXPIRY_DATE from dba_users where username = 'SEC';

USERNAME   ACCOUNT_STATUS       LOCK_DATE           EXPIRY_DATE
---------- -------------------- ------------------- -------------------
SEC        OPEN

sys@ora10g> select USERNAME,ACCOUNT_STATUS,LOCK_DATE,EXPIRY_DATE from dba_users where username = 'SEC';

USERNAME   ACCOUNT_STATUS       LOCK_DATE           EXPIRY_DATE
---------- -------------------- ------------------- -------------------
SEC        LOCKED(TIMED)        2009-10-11 16:05:03 2009-12-09 08:46:36

7)既然預設的PROFILE發生了變化,那麼就會面臨一個實際問題,如何恢復成原始狀態呢?這裡給出一個比較簡單的方法,就是使用ALTER PROFILE命令修改成原來的模樣
sys@ora10g> ALTER PROFILE DEFAULT LIMIT
  2   COMPOSITE_LIMIT             UNLIMITED
  3   SESSIONS_PER_USER           UNLIMITED
  4   CPU_PER_SESSION             UNLIMITED
  5   CPU_PER_CALL                UNLIMITED
  6   LOGICAL_READS_PER_SESSION   UNLIMITED
  7   LOGICAL_READS_PER_CALL      UNLIMITED
  8   IDLE_TIME                   UNLIMITED
  9   CONNECT_TIME                UNLIMITED
 10   PRIVATE_SGA                 UNLIMITED
 11   FAILED_LOGIN_ATTEMPTS       10
 12   PASSWORD_LIFE_TIME          UNLIMITED
 13   PASSWORD_REUSE_TIME         UNLIMITED
 14   PASSWORD_REUSE_MAX          UNLIMITED
 15   PASSWORD_VERIFY_FUNCTION    NULL
 16   PASSWORD_LOCK_TIME          UNLIMITED
 17   PASSWORD_GRACE_TIME         UNLIMITED
 18  /

Profile altered.

8)最後我們重新建立一下這個實驗PROFILE:sec_profile,可以預測,這次一定會成功滴~~~
sys@ora10g> CREATE PROFILE sec_profile LIMIT
  2     SESSIONS_PER_USER          UNLIMITED
  3     CPU_PER_SESSION            UNLIMITED
  4     CPU_PER_CALL               6000
  5     CONNECT_TIME               60
  6     LOGICAL_READS_PER_SESSION  DEFAULT
  7     LOGICAL_READS_PER_CALL     6000
  8     COMPOSITE_LIMIT            6000000
  9     PRIVATE_SGA                66K
 10     FAILED_LOGIN_ATTEMPTS      6
 11     PASSWORD_LIFE_TIME         60
 12     PASSWORD_REUSE_TIME        60
 13     PASSWORD_REUSE_MAX         5
 14     PASSWORD_LOCK_TIME         1/24
 15     PASSWORD_GRACE_TIME        10  
 16     PASSWORD_VERIFY_FUNCTION   verify_function
 17  /

Profile created.

建立成功鳥~~
在這個實驗中,我們使用了PROFILE幾乎所有的引數,惟一沒有包含的引數是IDLE_TIME,目的僅僅是為了說明一個細節:如果該PROFILE被授權給使用者後,這個被省略的IDLE_TIME引數將繼承預設PROFILE “DEFALT”中的定義。

對上面我們建立的PROFILE逐行做一下詮釋,以便加深理解:
第 2行:對使用者的併發連線會話數不做限制
第 3行:對於連線到使用者的每一個session的CPU時間的使用不做限制
第 4行:一次呼叫消耗的CPU時間不能超過60秒(不超過一分鐘)
第 5行:連線到使用者的每次會話時間不能超過60分鐘(不超過一個小時)
第 6行:一次會話使用的物理讀與邏輯讀資料塊總量與DEFAULT profile中定義保持一致
第 7行:一次呼叫使用的物理讀與邏輯讀資料塊總量不超過6000個資料塊
第 8行:一次會話總的資源消耗不超過6000000個服務單元(service units)
第 9行:一次會話在SGA中不能分配超過66K的空間
第10行:帳戶被鎖定之前允許6次的錯誤嘗試
第11行:超過此生命週期後密碼作廢
第12行:密碼重用時間60天
第13行:密碼重用之前密碼需要完成5次改變
第14行:超過錯誤嘗試次數後,使用者將被鎖定1小時
第15行:當密碼過期之後原密碼還可以使用10天
第16行:使用密碼複雜度校驗函式verify_function對密碼做檢查

再單獨深入解釋一下第12行和13行組合搭配之後的含義:也就是說只有完成了5次的密碼修改後並且已經超過60天后,之前的密碼才能夠再一次被使用。

9)透過dba_profiles檢視再一次檢視一下此時系統中存在的PROFILE的資訊
sys@ora10g> col PROFILE for a12
sys@ora10g> col RESOURCE_NAME for a25
sys@ora10g> col LIMIT for a15
sys@ora10g> select * from dba_profiles order by 1,2;

PROFILE      RESOURCE_NAME             RESOURCE LIMIT
------------ ------------------------- -------- ---------------
DEFAULT      COMPOSITE_LIMIT           KERNEL   UNLIMITED
DEFAULT      CONNECT_TIME              KERNEL   UNLIMITED
DEFAULT      CPU_PER_CALL              KERNEL   UNLIMITED
DEFAULT      CPU_PER_SESSION           KERNEL   UNLIMITED
DEFAULT      FAILED_LOGIN_ATTEMPTS     PASSWORD 3
DEFAULT      IDLE_TIME                 KERNEL   UNLIMITED
DEFAULT      LOGICAL_READS_PER_CALL    KERNEL   UNLIMITED
DEFAULT      LOGICAL_READS_PER_SESSION KERNEL   UNLIMITED
DEFAULT      PASSWORD_GRACE_TIME       PASSWORD 10
DEFAULT      PASSWORD_LIFE_TIME        PASSWORD 60
DEFAULT      PASSWORD_LOCK_TIME        PASSWORD .0006
DEFAULT      PASSWORD_REUSE_MAX        PASSWORD UNLIMITED
DEFAULT      PASSWORD_REUSE_TIME       PASSWORD 1800
DEFAULT      PASSWORD_VERIFY_FUNCTION  PASSWORD VERIFY_FUNCTION
DEFAULT      PRIVATE_SGA               KERNEL   UNLIMITED
DEFAULT      SESSIONS_PER_USER         KERNEL   UNLIMITED
SEC_PROFILE  COMPOSITE_LIMIT           KERNEL   5000000
SEC_PROFILE  CONNECT_TIME              KERNEL   45
SEC_PROFILE  CPU_PER_CALL              KERNEL   3000
SEC_PROFILE  CPU_PER_SESSION           KERNEL   UNLIMITED
SEC_PROFILE  FAILED_LOGIN_ATTEMPTS     PASSWORD 5
SEC_PROFILE  IDLE_TIME                 KERNEL   DEFAULT
SEC_PROFILE  LOGICAL_READS_PER_CALL    KERNEL   1000
SEC_PROFILE  LOGICAL_READS_PER_SESSION KERNEL   DEFAULT
SEC_PROFILE  PASSWORD_GRACE_TIME       PASSWORD 10
SEC_PROFILE  PASSWORD_LIFE_TIME        PASSWORD 60
SEC_PROFILE  PASSWORD_LOCK_TIME        PASSWORD .0416
SEC_PROFILE  PASSWORD_REUSE_MAX        PASSWORD 5
SEC_PROFILE  PASSWORD_REUSE_TIME       PASSWORD 60
SEC_PROFILE  PASSWORD_VERIFY_FUNCTION  PASSWORD VERIFY_FUNCTION
SEC_PROFILE  PRIVATE_SGA               KERNEL   15360
SEC_PROFILE  SESSIONS_PER_USER         KERNEL   UNLIMITED

32 rows selected.

10)刪除PROFILE
既然有建立,就一定對應著刪除,刪除方法很簡單,語法如下:
DROP PROFILE profile [ CASCADE ] ;

如果建立的PROFILE已經授權給了具體的使用者,則需要使用CASCADE選項級聯的收回相應的限制資訊,在收回這些限制資訊之後將會以系統預設的PROFILE對該使用者進行限制。
刪除示例如下:
sys@ora10g> drop profile SEC_PROFILE cascade;

Profile dropped.

如果該PROFILE已經授權給具體的使用者,使用不帶有cascade選項的刪除命令將得到如下的報錯資訊:
sys@ora10g> drop profile SEC_PROFILE;
drop profile SEC_PROFILE
*
ERROR at line 1:
ORA-02382: profile SEC_PROFILE has users assigned, cannot drop without CASCADE


6.關於PROFILE內容何時生效的一點注意事項
這裡討論需要談到一個系統引數,它就是resource_limit。

如果要開啟“資源限制”的話,這個引數必須是“TRUE”的狀態
sys@ora10g> show parameter resource_limit

NAME            TYPE                 VALUE
--------------- -------------------- ----------------------
resource_limit  boolean              FALSE

這裡有一個小細節不得不提:
之所以稱這個引數為resource_limit(資源限制)而沒有稱作“profile_limit”,是因為這個引數只對PROFILE中的資源限制部分起作用,如果是預設的FALSE狀態,表示PROFILE定義中的資源限制條件不起作用,只有該引數為TRUE時,資源限制的定義才生效。
不過,關於PROFILE中密碼限制的條件則與這個引數無關,無論這個引數設定為什麼值,有關密碼限制的條件都會預設生效,從這個細節上可以看出來Oracle對使用者密碼的重視程度。

因此關於PROFILE的生效情況結論是:
1)使用者所有擁有的PROFILE中有關密碼的限制永遠生效,不受限制。
2)使用者所有擁有的PROFILE中有關資源的限制與resource_limit引數的設定有關,當為TRUE時生效,當為FALSE時(預設值是FALSE)無效。

7.一切都OK了,最後我們來演示一下將新建立的PROFILE sec_profile指定給具體使用者sec的操作
sys@ora10g> alter user sec profile sec_profile;

User altered.

sys@ora10g> select USERNAME,PROFILE from dba_users where USERNAME = 'SEC';
                                                                          
USERNAME   PROFILE                                                       
---------- ------------                                                  
SEC        SEC_PROFILE                                                   

8.【附】密碼驗證函式VERIFY_FUNCTION的建立指令碼內容utlpwdmg.sql,供參考。
ora10g@secDB /home/oracle$ cat $ORACLE_HOME/rdbms/admin/utlpwdmg.sql
Rem
Rem $Header: utlpwdmg.sql 31-aug-2000.11:00:47 nireland Exp $
Rem
Rem utlpwdmg.sql
Rem
Rem  Copyright (c) Oracle Corporation 1996, 2000. All Rights Reserved.
Rem
Rem    NAME
Rem      utlpwdmg.sql - script. for Default Password Resource Limits
Rem
Rem    DESCRIPTION
Rem      This is a script. for enabling the password management features
Rem      by setting the default password resource limits.
Rem
Rem    NOTES
Rem      This file contains a function for minimum checking of password
Rem      complexity. This is more of a sample function that the customer
Rem      can use to develop the function for actual complexity checks that the
Rem      customer wants to make on the new password.
Rem
Rem    MODIFIED   (MM/DD/YY)
Rem    nireland    08/31/00 - Improve check for username=password. #1390553
Rem    nireland    06/28/00 - Fix null old password test. #1341892
Rem    asurpur     04/17/97 - Fix for bug479763
Rem    asurpur     12/12/96 - Changing the name of password_verify_function
Rem    asurpur     05/30/96 - New script. for default password management
Rem    asurpur     05/30/96 - Created
Rem

-- This script. sets the default password resource parameters
-- This script. needs to be run to enable the password features.
-- However the default resource parameters can be changed based
-- on the need.
-- A default password complexity function is also provided.
-- This function makes the minimum complexity checks like
-- the minimum length of the password, password not same as the
-- username, etc. The user may enhance this function according to
-- the need.
-- This function must be created in SYS schema.
-- connect sys/<password> as sysdba before running the script

CREATE OR REPLACE FUNCTION verify_function
(username varchar2,
  password varchar2,
  old_password varchar2)
  RETURN boolean IS
   n boolean;
   m integer;
   differ integer;
   isdigit boolean;
   ischar  boolean;
   ispunct boolean;
   digitarray varchar2(20);
   punctarray varchar2(25);
   chararray varchar2(52);

BEGIN
   digitarray:= '0123456789';
   chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
   punctarray:='!"#$%&()``*+,-/:;<=>?_';

   -- Check if the password is same as the username
   IF NLS_LOWER(password) = NLS_LOWER(username) THEN
     raise_application_error(-20001, 'Password same as or similar to user');
   END IF;

   -- Check for the minimum length of the password
   IF length(password) < 4 THEN
      raise_application_error(-20002, 'Password length less than 4');
   END IF;

   -- Check if the password is too simple. A dictionary of words may be
   -- maintained and a check may be made so as not to allow the words
   -- that are too simple for the password.
   IF NLS_LOWER(password) IN ('welcome', 'database', 'account', 'user', 'password', 'oracle', 'computer', 'abcd') THEN
      raise_application_error(-20002, 'Password too simple');
   END IF;

   -- Check if the password contains at least one letter, one digit and one
   -- punctuation mark.
   -- 1. Check for the digit
   isdigit:=FALSE;
   m := length(password);
   FOR i IN 1..10 LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(digitarray,i,1) THEN
            isdigit:=TRUE;
             GOTO findchar;
         END IF;
      END LOOP;
   END LOOP;
   IF isdigit = FALSE THEN
      raise_application_error(-20003, 'Password should contain at least one digit, one character and one punctuation');
   END IF;
   -- 2. Check for the character
   <<findchar>>
   ischar:=FALSE;
   FOR i IN 1..length(chararray) LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(chararray,i,1) THEN
            ischar:=TRUE;
             GOTO findpunct;
         END IF;
      END LOOP;
   END LOOP;
   IF ischar = FALSE THEN
      raise_application_error(-20003, 'Password should contain at least one \
              digit, one character and one punctuation');
   END IF;
   -- 3. Check for the punctuation
   <<findpunct>>
   ispunct:=FALSE;
   FOR i IN 1..length(punctarray) LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(punctarray,i,1) THEN
            ispunct:=TRUE;
             GOTO endsearch;
         END IF;
      END LOOP;
   END LOOP;
   IF ispunct = FALSE THEN
      raise_application_error(-20003, 'Password should contain at least one \
              digit, one character and one punctuation');
   END IF;

   <<endsearch>>
   -- Check if the password differs from the previous password by at least
   -- 3 letters
   IF old_password IS NOT NULL THEN
     differ := length(old_password) - length(password);

     IF abs(differ) < 3 THEN
       IF length(password) < length(old_password) THEN
         m := length(password);
       ELSE
         m := length(old_password);
       END IF;

       differ := abs(differ);
       FOR i IN 1..m LOOP
         IF substr(password,i,1) != substr(old_password,i,1) THEN
           differ := differ + 1;
         END IF;
       END LOOP;

       IF differ < 3 THEN
         raise_application_error(-20004, 'Password should differ by at \
         least 3 characters');
       END IF;
     END IF;
   END IF;
   -- Everything is fine; return TRUE ;
   RETURN(TRUE);
END;
/

-- This script. alters the default parameters for Password Management
-- This means that all the users on the system have Password Management
-- enabled and set to the following values unless another profile is
-- created with parameter values set to different value or UNLIMITED
-- is created and assigned to the user.

ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME 60
PASSWORD_GRACE_TIME 10
PASSWORD_REUSE_TIME 1800
PASSWORD_REUSE_MAX UNLIMITED
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LOCK_TIME 1/1440
PASSWORD_VERIFY_FUNCTION verify_function;


仔細閱讀上面的指令碼,您可以得到關於verify_function函式的密碼複雜性校驗規則如下:
1)密碼最小長度為4個字元
2)密碼不能和使用者名稱相同
3)密碼要包含至少一個字元、一個數字和一個特殊字元
4)密碼需要至少有3個字元與之前的口令不相同

9.小結
透過PROFILE對使用者的資源和登入密碼的限制方法使用起來還是很貼心的,畢竟Oracle提供了這樣一種便捷的管理手段,對付資料庫方面的一般性審計還是遊刃有餘的,即使這些規則仍然不能滿足需求,Oracle也提供了新增和修改的介面,以便按需定製,當然會有一定的開發週期和成本。

Oracle對資料庫的安全性方面提供了非常多的手段來保證,如審計和許可權控制等優秀手段。對於一個商業資料庫的安全性審計是非常重要的,如果後臺的資料庫存在安全隱患,可以說必定會帶來一場浩劫,只是早晚的事情。如果您是一名維護DBA,一定要從資料庫的安全性上多多動腦筋,不要等待問題出現了才恍然大悟:哇塞,原來Oracle同學早就有補救的措施啦!

BTW:關於許可權控制的策略在使用前一定要做好充分的測試,確保對每一條限制規則理解透徹,不然會帶來不必要的麻煩,另外一個經驗就是:將每一步的限制規則記錄到一個特定的資料庫維護手冊中,方便查詢,同時也便於知識的傳承,利己利人,“好事兩樁”。

-- The End --

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29067253/viewspace-2006088/,如需轉載,請註明出處,否則將追究法律責任。

相關文章