分享Profile設定高標準密碼複雜度的方法

zhcunique發表於2021-02-08

Profile是Oracle提供的一種針對使用者資源使用和密碼管理的策略配置。藉助Profile,可以實現特定使用者資源上的限制和密碼管理規則的應用。在實際的應用中,Profile可以幫助我們實現很多應用層面比較困難實現的需求。預設情況下,使用者連線資料庫,形成會話,使用CPU資源和記憶體資源是沒有限制的。在一些應用併發量很大,特別是多個應用部署在同一個資料庫伺服器上的時候,依據應用對企業重要程度的部分,CPU和記憶體資源的分配一定是有所側重的。  此外,使用者的密碼管理,可以是一個比較複雜的工作。比如,使用者鎖定之後,多長時間被自動釋放、密碼生命週期、登入嘗試次數等等。這兩個方面的問題,都可以藉助Profile去解決。Profile相當於一個命名的安全策略集合,其中規定了資源使用的限制和密碼使用的規則。Profile定義之後,是可以應用到每個使用者上,對每個使用者的安全活動進行限制。

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


上面標紅的專案為資料庫使用者密碼複雜度要求函式,不同企業根據自身規章制度,對資料庫使用者密碼複雜度要求不一,需要根據自身要求編寫各自的複雜度函式,以下分享筆者所使用的複雜度限制函式原始碼,該函式限制策略為至少12位,且同時包含數字、字母和特殊字元。

CREATE OR REPLACE FUNCTION verify_function_11G_dx
(username varchar2,
  password varchar2,
  old_password varchar2)
  RETURN boolean IS
   n boolean;
   m integer;
   differ integer;
   isdigit boolean;
   ischar  boolean;
   issign  boolean;
   ispunct boolean;
   db_name varchar2(40);
   digitarray varchar2(20);
   punctarray varchar2(25);
   chararray varchar2(52);
   signarray varchar2(50);
   i_char varchar2(10);
   simple_password varchar2(10);
   reverse_user varchar2(32);

BEGIN
   digitarray:= '0123456789';
   chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
   signarray:= '@!#$%^&*()_-=+*,.?;~`';

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


   -- Check if the password is same as the username or username(1-100)
   IF NLS_LOWER(password) = NLS_LOWER(username) THEN
     raise_application_error(-20002, 'Password same as or similar to user');
   END IF;
   FOR i IN 1..100 LOOP
      i_char := to_char(i);
      if NLS_LOWER(username)|| i_char = NLS_LOWER(password) THEN
        raise_application_error(-20005, 'Password same as or similar to user name ');
      END IF;
    END LOOP;

   -- Check if the password is same as the username reversed
   
   FOR i in REVERSE 1..length(username) LOOP
     reverse_user := reverse_user || substr(username, i, 1);
   END LOOP;
   IF NLS_LOWER(password) = NLS_LOWER(reverse_user) THEN
     raise_application_error(-20003, 'Password same as username reversed');
   END IF;

   -- Check if the password is the same as server name and or servername(1-100)
   select name into db_name from sys.v$database;
   if NLS_LOWER(db_name) = NLS_LOWER(password) THEN
      raise_application_error(-20004, 'Password same as or similar to server name');
   END IF;
   FOR i IN 1..100 LOOP
      i_char := to_char(i);
      if NLS_LOWER(db_name)|| i_char = NLS_LOWER(password) THEN
        raise_application_error(-20005, 'Password same as or similar to server name ');
      END IF;
    END LOOP;

   -- 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 ('welcome1', 'database1', 'account1', 'user1234', 'password1', 'oracle123', 'computer1', 'abcdefg1', 'change_on_install','123456','oracle') THEN
      raise_application_error(-20006, 'Password too simple');
   END IF;

   -- Check if the password is the same as oracle (1-100)
    simple_password := 'oracle';
    FOR i IN 1..100 LOOP
      i_char := to_char(i);
      if simple_password || i_char = NLS_LOWER(password) THEN
        raise_application_error(-20007, 'Password too simple ');
      END IF;
    END LOOP;

   -- Check if the password contains at least one letter, one digit
   -- 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(-20008, 'Password must contain at least one digit, one character');
   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 findsign;
         END IF;
      END LOOP;
   END LOOP;
   IF ischar = FALSE THEN
      raise_application_error(-20009, 'Password must contain at least one \
              digit, and one character');
   END IF;


   -- 2.1 Check for the sign
   <<findsign>>
   issign:=FALSE;
   FOR i IN 1..length(signarray) LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(signarray,i,1) THEN
            issign:=TRUE;
             GOTO endsearch;
         END IF;
      END LOOP;
   END LOOP;
   IF issign = FALSE THEN
      raise_application_error(-20010, 'Password must contain at least one \
              digit, and one character , and one sign');
   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);

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

       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(-20011, 'Password should differ from the \
            old password by at least 3 characters');
       END IF;
     END IF;
   END IF;
   -- Everything is fine; return TRUE ;   
   RETURN(TRUE);
END;
/

GRANT EXECUTE ON verify_function_11G_dx TO PUBLIC;

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

相關文章