1. 程式人生 > 其它 >postgresql-限制使用者登入錯誤次數

postgresql-限制使用者登入錯誤次數

原文https://blog.csdn.net/weixin_39540651/article/details/108227188
【等保用】

在oracle中我們可以通過設定FAILED_LOGIN_ATTEMPTS來限制使用者密碼登入錯誤的次數,但是在postgresql中是不支援這個功能的。儘管PostgreSQL支援event trigger,可是event侷限於DDL,對於登入登出事件是沒辦法使用event trigger的。

不過像登入新建會話觸發某個事件這個需求可以通過hook實現,不過該方法比較複雜,需要修改核心程式碼,在客戶端認證中新增邏輯,判斷輸入密碼次數統計。這裡推薦一種比較簡單的方法實現類似的功能。

這裡我們要使用到session_exec這個外掛,使用該外掛會在登入時執行一個指定的function。

下載地址:
https://github.com/okbob/session_exec

下載解壓之後需要進行以下配置:

set session_preload_libraries to session_exec
set session_exec.login_name to name of your login function
該外掛有以下特點:

如果函式不存在則會進行警告;
函式執行失敗則不允許連線。
利用該外掛我們可以寫一個簡單的函式來實現限制使用者登入錯誤次數的功能。

例子:
1、建立外部表記錄資料庫日誌資訊。

CREATE SERVER pglog FOREIGN DATA WRAPPER file_fdw;

CREATE FOREIGN TABLE pglog (
log_time timestamp(3) with time zone,
user_name text,
database_name text,
process_id integer,
connection_from text,
session_id text,
session_line_num bigint,
command_tag text,
session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_pos integer,
context text,
query text,
query_pos integer,
location text,
application_name text,
backend_type text
) SERVER pglog
OPTIONS ( program 'find $PGDATA/log -type f -name "*.csv" -mtime -1 -exec cat {} ;', format 'csv' );

2、建立表t_login提取資料庫日誌中的登入資訊。

create table t_login
(
login_time timestamp(3) with time zone --插入時間,
user_name text,
flag int --標誌位,0代表過期資料
);

插入登入資訊:

bill=# insert into t_login select log_time,user_name from pglog where command_tag='authentication' and error_severity= 'FATAL'
bill-# ;
INSERT 0 4

3、建立登入執行的function

create or replace function lock_user() returns void as $$
declare
res text;
c1 timestamp(3) with time zone;
begin
select login_time from t_login where flag = 0 order by login_time desc limit 1 into c1; --獲取當前日誌中最新時間
insert into t_login select log_time,user_name from pglog where command_tag='authentication' and error_severity= 'FATAL' and log_time > c1; --將最新的資料插入t_login表
update t_login set flag = 1 where login_time > c1;
for res in select user_name from t_login where flag = 1 group by user_name having count(*) >=3 --檢查登入失敗次數是否大於3,若大於3則鎖定使用者
loop
EXECUTE format('alter user %I nologin',res); --鎖定使用者
EXECUTE 'select pg_terminate_backend(pid) from pg_stat_activity where usename=$1' using res; --斷開當前被鎖定使用者會話
raise notice 'Account % is locked!',res;
end loop;
end;
$$ language plpgsql strict;

4、編輯postgresql.conf檔案,配置登入函式

session_preload_libraries='session_exec'
session_exec.login_name='lock_user'

5、測試
模擬test1使用者登入錯誤超過3次:

bill=# select * from t_login;
login_time | user_name | flag
----------------------------+-----------+------
2020-08-26 07:26:45.42+08 | test1 | 1
2020-08-26 07:26:50.179+08 | test1 | 1
2020-08-26 07:26:52.487+08 | test1 | 1
2020-08-26 07:26:54.537+08 | test1 | 1
(4 rows)

當我們在使用test1使用者登入時則無法連線

pg13@cnndr4pptliot-> psql bill test1
Password for user test1:
NOTICE: c1 =
psql: error: could not connect to server: FATAL: terminating connection due to administrator command
CONTEXT: SQL statement "select pg_terminate_backend(pid) from pg_stat_activity where usename=$1"
PL/pgSQL function lock_user() line 13 at EXECUTE

再次登入可以看到提示該使用者被鎖定:

pg13@cnndr4pptliot-> psql bill test1
Password for user test1:
psql: error: could not connect to server: FATAL: role "test1" is not permitted to log in

6、解鎖使用者
此時想要解鎖該使用者則需要執行:

bill=# alter user test1 login;
ALTER ROLE

然後需要注意還要將t_login中過期的資料修改。

bill=# update t_login set flag = 0;
UPDATE 4

參考連結:
https://github.com/okbob/session_exec
————————————————

本文來自部落格園,作者:{dyy},轉載請註明原文連結:{https://www.cnblogs.com/ddlearning/}

好好學習,天天向上