PostgreSQL用戶(hù)登錄失敗自動(dòng)鎖定的處理方案
更新時(shí)間:2026-05-05 00:13:04
一、失敗鎖定插件session_exec安裝配置篇
下載插件并編譯安裝。自動(dòng)
https://github.com/okbob/session_exec
$ unzip session_exec-master?.zip
$ cd session_exec-master/
$ make pgヽ(′ー`)ノ_config=/opt/pgsql/bin/pg_con???fig
$ make pg_config=/opt/pgsql/bin/pg_config install
配置(′▽?zhuān)?pos??tgr??esql.conf。理方
session_preload_libraries='se(°□°)ssion_(╯‵□′)╯ex??ec'
session_exec.lo(′▽?zhuān)?)gin_name='login'
注意:上面第一個(gè)變量是用戶(hù)設(╬?益?)置session_preload_libraries而不是通常(′▽?zhuān)?設置的shared_preload_libraries。
第二個(gè)變量是登錄的處??需要自定義實(shí)現的登錄函數。
1$ sudo systemctl restartヽ(′▽?zhuān)?ノ postgresql-12
二、自動(dòng)自定義登錄函數篇
創(chuàng )建t_login表用于存儲提取自數據庫日志中登錄失敗的理方信息。
create table t_login
(
login_time timestamp(3) with time zone --插入時(shí)間,用戶(hù)
user_name text --數據庫登錄用戶(hù),
flag int4 --標志位,(′ω`)0代表過(guò)期數據??,登錄的處1代表正常狀態(tài)數據
);
使用file_fdw外部表記錄數據庫日志信息。失敗鎖定
file_fdw如果未配置過(guò),自動(dòng)參見(jiàn)下面步驟。理方
$ cd /opt/postgresql-12.5/contrib/file_fdw
$ make && make inst??all
create extension file_fdw;
CR(?????)EATE SERVER pglog FOREIGN DATA WRAPPER(/ω\) file_fdw;
CREATE FOR(′ω`)EIGN TABLE postgres_log(
log_time timestamp(3) with time zone,(◎_◎;)
user_name?? text,
database_name text,
process_id integer,
connection_from text,
session_id te???xt,
session_line_n??um bigint,
command_tag text,
session_start_time timestamp with time zone,
v(′;д;`)irtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_p??os integ??er,
context text,
query text,
query_pos integer,
location text,
ap( ?ω?)plication?_name text
) SERVER?? pglog
OPTIONS ( program 'find /opt/pg_log_5432 -type f -name "*.csv" -mtime -1 -exec cat { } \;', format 'csv' );
注??意:
1./opt/pg_log_??5432需要修改為實(shí)際環(huán)境日志目錄。
2. 不同PG版本csv日志格式可能有所差??異,參考PG官網(wǎng)??文檔runtime-config-logging章節(http://post??greヽ(′▽?zhuān)?ノs.cn/docs/12/runtime-config-logging.html)。
此時(shí)連接數據庫因未創(chuàng )建登錄函數會(huì )出現下面的警告信息。
$ psql -Upostgres
WARNING: function "login()" does not exist
psql (12.5)
Type "help" for help.
創(chuàng )建登錄函數login。
create or replace function login() returns void as $$
declare
res text;
c1 timestamp(3) with time zone;
begin
--獲取當前日志中最新時(shí)間
select login_time
from public.t_login
where flag = 0
order by login_time
desc limit 1
into c1;
--將最新的數據插入t_login表
insert into public.t_login
select log_time,user_name
from public.postgres_log
wher??e command_tag='authentication'
a(??ヮ?)?*:???nd error_severity= 'FATAL'
and log_time > c1;
update public.t_login set flag = 1 where lo??g?in_time > c1;
--檢查登錄失敗次數是否大于3,若大于3則鎖定用(yong)戶(hù)
for res in select user_name from public.t_??login where flag = 1 gro(╯°□°)╯︵ ┻━┻up by user_name having count(*)?? >=3
loop='loop'
--鎖定用戶(hù)
EXECUTE format??('alter user %I nologin',res);
--斷開(kāi)當前被鎖定用戶(hù)會(huì )話(huà)
EXECUTE 'select pg_catalog.pg_terminate_backend(pid) from pg_catalog??.pg_stat_activity where(′▽?zhuān)? usena(╯‵□′)╯me=$1' using res;
raise notice 'Account % is locked!',res;
end loop="";
end;
$$ language plpgsql strict security definer set search_path to 'public';
測試使用篇
創(chuàng )建測試用戶(hù)。
1c??rea(′?`*)te user test1 encrypted password 'X??XX';
模擬test1用戶(hù)登錄失敗,輸入錯誤密碼?。
$ psql -h192.168.137.11 -Utest1 postgres
Passwo?rd for user teヽ(′?`)ノst1:
psql: erro(??-)?r: FATAL: password authentication failed for user "test1"
通過(guò)外部表查看登錄失敗的日志。
可(ke)以看到1條(tiao)數據,手工插入一條登錄失敗的信息到t_login表。
insert into(′▽?zhuān)?) t_login select log_time,user_name,0
from postgres_log
where command_tag='authentication'
and error_severity= 'FATAL';(°ロ°) !
參考上面登錄失敗測試,接著(zhù)再測試2次。
然后使用postgres用戶(hù)登錄數據庫,觀(guān)察t_login表數據。
postgres=# select * from t_(′?`*)login;
login_time | user_name | flag
-------------(╬ ò﹏ó)------------+-----------+------
2021-02-08 06:24:47.101 | test1 | 0
20( ?ω?)21-02-08 06:25??:16.581 | test1 | 1
2021-02-08 06:??25:18.429 | test1 | 1
(3 rows)
再測試兩次失敗??登錄,然后使用??postgres用戶(hù)登錄數據庫,看到提示ヽ(′ー`)ノ該用戶(hù)被鎖定。
[postgres@node11 ~]$ psql
NOTICE:?? Account test1 is locked!
psql (12.5)
Type "help" for help.
postgres=# se??lect * from t_login;
login_time | user_name | flag
-------------------------+-----------+------
2021-02-08 06:45:38.017 | test1 | 0
2021-02-08 06:45:58.??809 | test1(′_`) | 1
2021-02-08 06:45:58.809 | test1 | 1
2021-02-08 06:46:08.116 | test1 | 1
202ヾ(′ω`)?1-02-08 06:46:11.986 | test1 | 1
(5 rows)
解鎖用戶(hù)。
1update t_login set flag = 0 where user_name='test1' and flag=1;
session_exec通過(guò)用戶(hù)登錄成功后調用login函數去實(shí)現鎖定登錄失敗次數過(guò)多的用戶(hù)。
此種方式有點(diǎn)繁瑣且會(huì )造成數據庫連接變慢。
文章(′▽?zhuān)?)來(lái)源:腳本之家
來(lái)源地址:https://www.jb51.net/article/208017.htm

