1. 相關背景
MySQL提供了一個參數
init_connect
用來控制當用戶登陸時默認執行指定命令,雖然會執行,但不會返回任何結果,但可以將執行的結果保存到表中記錄,我們可以利用這個特性來記錄用戶登錄數據庫的行爲日誌
2. 操作步驟
- 創建一張登錄日誌表,包含以下信息
- 數據庫中對應的用戶
- 連接數據庫的IP或主機名
- 訪問的數據庫
- 登錄數據庫後分配的連接ID
- 登錄數據庫的時間
- 對數據庫中所有用戶都授予登錄日誌表的查詢和插入權限
該步驟十分關鍵
,如果用戶沒該表的相應權限,會導致設置了init_connect參數後用戶無法登錄
- 配置init_connect參數觸發用戶登錄時自動插入一條登錄日誌
- 驗證可用性
1. 創建一張登錄日誌表
CREATE TABLE `mysql`.`audit_login` (
`ID` bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`USER` varchar(128) NOT NULL COMMENT '數據庫中的用戶',
`HOST` varchar(64) DEFAULT NULL COMMENT '登錄的IP',
`DB` varchar(64) DEFAULT NULL COMMENT '訪問的數據庫',
`PROCESSLIST_ID` bigint NOT NULL COMMENT '用戶連接',
`LOGIN_TIME` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '登錄時間',
`UPDATE_TIME` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '記錄這行數據上次被修改的時間,默認等於LOGIN_TIME',
PRIMARY KEY (`ID`),
KEY `IDX_USER` (`USER`),
KEY `IDX_HOST` (`HOST`),
KEY `IDX_LOGIN_TIME` (`LOGIN_TIME`)
) ENGINE=InnoDB COMMENT "用戶登錄審計日誌表";
2. 生成對訪問日誌表的授權操作
這裏生成的授權語句會排除內部用戶和有super權限的用戶
-- 批量生成授權語句的SQL
-- 查詢權限可以不授予,可根據具體情況調整
select concat("grant select,insert on mysql.audit_login to '",user,"'@'",host,"';") grants_sql from mysql.user where user not in ('mysql.session','mysql.sys') and Super_priv='N';
-- 輸出示例
+-------------------------------------------------------------+
| grants_sql |
+-------------------------------------------------------------+
| grant select,insert on mysql.audit_login to 'zhenxing'@'%'; |
| grant select,insert on mysql.audit_login to 'bbb'@'%'; |
+-------------------------------------------------------------+
3. 配置init_connect參數
先在數據庫中用
set global
動態設置並驗證生效後在配置到my.cnf文件中
set global init_connect="insert into mysql.audit_login(USER,HOST,DB,PROCESSLIST_ID) values(current_user(),substring_index(user(),'@',-1),database(),connection_id());";
-- my.cnf文件中的配置方法
[mysqld]
init_connect="insert into mysql.audit_login(USER,HOST,DB,PROCESSLIST_ID) values(current_user(),substring_index(user(),'@',-1),database(),connection_id());";
4. 驗證有效性
使用沒有super權限的用戶登錄數據庫並查詢mysql.audit_login是否有記錄即可
注意:該表中的PROCESSLIST_ID對應的binlog日誌中的thread_id,可以使用這個來觀測該用戶登錄到數據庫後的修改操作,但由於binlog不記錄查詢操作,所以不支持對查詢操作的匹配.
3. 限制條件
- 不會記錄有super權限的用戶的登錄操作
- 防止在不允許重啓的情況下因爲init_connect配置錯誤導致有super權限的用戶也登不上數據庫
- 密碼過期的用戶不會記錄也不會報錯
- 需要給到密碼過期的用戶修改密碼的機會,不能在登錄時就報錯
- 只記錄登入行爲,不記錄登出行爲
- 不記錄登錄數據庫後的增刪改查操作
- 有連接池的情況下,連接會被複用,不一定能一一對應
- 使用價值不會太高,要細化還是需要專有的審計插件