函數簽名:verify_function(username, password, old_password) RETURN BOOLEAN
掛載方式:ALTER PROFILE default LIMIT PASSWORD_VERIFY_FUNCTION verify_function;
welcome, database, account, user, password, oracle, computer, abcd。CREATE OR REPLACE FUNCTION sys.verify_function (
username VARCHAR2,
password VARCHAR2,
old_password VARCHAR2
) RETURN BOOLEAN IS
v_digit_arr VARCHAR2(20) := '0123456789';
v_char_arr VARCHAR2(52) := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
v_punct_arr VARCHAR2(25) := '!"#$%&()``*+,-/:;<=>?_';
v_has_digit BOOLEAN := FALSE;
v_has_char BOOLEAN := FALSE;
v_has_punct BOOLEAN := FALSE;
v_diff_cnt INTEGER := 0;
BEGIN
-- 1. 與使用者名比對
IF LOWER(password) = LOWER(username) THEN
RAISE_APPLICATION_ERROR(-20001, 'Password same as user');
END IF;
-- 2. 長度
IF LENGTH(password) < 8 THEN
RAISE_APPLICATION_ERROR(-20002, 'Password length less than 8');
END IF;
-- 3. 字典弱密碼
IF LOWER(password) IN ('welcome','database','account','user','password','oracle','computer','abcd') THEN
RAISE_APPLICATION_ERROR(-20003, 'Password too simple');
END IF;
-- 4. 複雜度:數字、字母、標點
FOR i IN 1..LENGTH(password) LOOP
IF INSTR(v_digit_arr, SUBSTR(password,i,1)) > 0 THEN v_has_digit := TRUE;
ELSIF INSTR(v_char_arr, SUBSTR(password,i,1)) > 0 THEN v_has_char := TRUE;
ELSIF INSTR(v_punct_arr, SUBSTR(password,i,1)) > 0 THEN v_has_punct := TRUE;
END IF;
END LOOP;
IF NOT (v_has_digit AND v_has_char AND v_has_punct) THEN
RAISE_APPLICATION_ERROR(-20004, 'Password must contain digit, char, punctuation');
END IF;
-- 5. 與舊密碼差異
IF old_password IS NOT NULL THEN
v_diff_cnt := ABS(LENGTH(old_password) - LENGTH(password));
FOR i IN 1..LEAST(LENGTH(password), LENGTH(old_password)) LOOP
IF SUBSTR(password,i,1) != SUBSTR(old_password,i,1) THEN v_diff_cnt := v_diff_cnt + 1; END IF;
END LOOP;
IF v_diff_cnt < 3 THEN
RAISE_APPLICATION_ERROR(-20005, 'Password must differ by at least 3 characters');
END IF;
END IF;
RETURN TRUE;
END;
/
ALTER PROFILE default LIMIT
PASSWORD_VERIFY_FUNCTION verify_function
PASSWORD_LIFE_TIME 90
PASSWORD_GRACE_TIME 7
FAILED_LOGIN_ATTEMPTS 5
PASSWORD_LOCK_TIME 1;
-- 應失敗:長度不足
ALTER USER scott IDENTIFIED BY abc123;
-- ORA-28003: password verification failed: Password length less than 8
-- 應成功
ALTER USER scott IDENTIFIED BY Str0ng!Pass;
DBMS_CRYPTO 檢測鍵盤連續鍵(如 qwerty、123456)。PASSWORD_VERIFY_FUNCTION 回傳 VARCHAR2 錯誤訊息,支援多語系。密碼驗證函數是資料庫第一道防線。建議依合規需求(PCI-DSS、GDPR、等保)調整規則,並納入 CI/CD 自動化測試,確保策略生效。