Khoá đăng nhập web wordpress nếu nhập mật khẩu sai quá x lần
Trên thị trường có rất nhiều plugin giống bạn phòng thủ trước Brute-force login attacks, 1 số plugin điển hình mà bạn có thể cài đặt như: Limit Login Attempts Reloaded, WP fail2ban – Advanced Security Plugin, SiteGuard WP Plugin … nhưng nếu bạn không muốn sử dụng plugin thì có thể sử dụng code dưới đây để thay thế.
Bạn copy code bên dưới đây và dán vào file
Ghi chú
Hàm đầu tiên,
functions.php
lưu lại là xong. File functions.php
nằm ở đâu thì bạn có thể đọc qua bài viết sau
Ở đoạn code dưới bạn nên thay đổi email, info@ngoinhaweb.vn để nếu ai đó đăng nhập thất bại hơn 5 lần sẽ có thông báo gửi về email cho bạn biết (lưu ý website phải cài SMTP thì hàm wp_mail
mới gửi được thông báo)
Code dưới là một giải pháp tùy chỉnh để hạn chế số lần đăng nhập vào trang web WordPress mà không cần sử dụng plugin. Mã sử dụng action wp_login_failed
và filter authenticate
và đặt attempted_login
transient. Số lần thử không thành công được lưu trữ tạm thời và được sử dụng để cảnh báo người dùng khi đạt đến giới hạn. Mã này cũng bao gồm chức năng tính toán thời gian còn lại cho đến khi người dùng có thể cố gắng đăng nhập lại sau khi bị chặn.
Bạn có thể thay số lần đăng nhập thất bại sẽ bị khoá ở dòng code $datas['tried'] >= 5
và if ( $datas['tried'] <= 5 ) {
thay 5 thành số bạn muốn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
add_filter( 'authenticate', 'ngoinhaweb_check_attempted_login', 30, 3 ); function ngoinhaweb_check_attempted_login( $user, $username, $password ) { if ( get_transient( 'attempted_login' ) ) { $datas = get_transient( 'attempted_login' ); if ( $datas['tried'] >= 5 ) { $until = get_option( '_transient_timeout_' . 'attempted_login' ); $time = ngoinhaweb_time_to_go( $until ); wp_mail( 'info@ngoinhaweb.com', 'Brute force login detected!', 'Brute force login detected!' ); return new WP_Error( 'too_many_tried', "<strong>ERROR</strong>: Bạn đã đạt đến giới hạn xác thực, bạn có thể thử lại sau $time." ); } } return $user; } add_action( 'wp_login_failed', 'ngoinhaweb_login_failed', 10, 1 ); function ngoinhaweb_login_failed( $username ) { if ( get_transient( 'attempted_login' ) ) { $datas = get_transient( 'attempted_login' ); $datas['tried']++; if ( $datas['tried'] <= 5 ) { set_transient( 'attempted_login', $datas, 300 ); } } else { $datas = [ 'tried' => 1, ]; set_transient( 'attempted_login', $datas, 300 ); } } function ngoinhaweb_time_to_go( $timestamp ) { // Convert the MySQL timestamp to PHP time $periods = [ 'giây', 'phút', 'giờ', 'ngày', 'tuần', 'tháng', 'năm', ]; $lengths = [ '60', '60', '24', '7', '4.35', '12', ]; $current_timestamp = time(); $difference = abs( $current_timestamp - $timestamp ); for ( $i = 0; $difference >= $lengths[ $i ] && $i < count( $lengths ) - 1; $i++ ) { $difference /= $lengths[ $i ]; } $difference = round( $difference ); if ( isset( $difference ) ) { // if ( (int) $difference !== 1 ) { // $periods[ $i ] .= 's'; // } $output = "$difference $periods[$i]"; return $output; } } |
ngoinhaweb_check_attempted_login
được nối với bộ lọc authenticate. Sử dụng get_transient
trong WordPress để lấy số lần đăng nhập thất bại. Nếu người dùng đã thử đăng nhập sai quá 5 lần, nó sẽ trả về lỗi WordPress về giới hạn đăng nhập không thành công và chặn người dùng đăng nhập trong một khoảng thời gian nhất định.
Chức năng ngoinhaweb_login_failed
được nối với action wp_login_failed
. Nó tăng số lần đăng nhập đã thử mỗi lần đăng nhập không thành công. Sau đó, số lần đăng nhập đã thử được đặt thành attempted_login
tạm thời, số này sẽ được sử dụng để chặn người dùng đăng nhập trong một khoảng thời gian tạm thời.
The ngoinhaweb_time_to_go
tính toán thời gian còn lại cho đến khi người dùng có thể thử đăng nhập lại sau khi bị chặn. Nó chuyển đổi dấu thời gian thành định dạng thời gian thân thiện với người dùng.
Hàm time()
để lấy thời gian hiện tại và hàm abs()
để tính chênh lệch tuyệt đối giữa thời gian hiện tại và thời gian người dùng bị chặn.
Ở trên là code đơn giản bạn có thể viết thêm chức năng log theo IP rồi gửi qua email thêm ví dụ 1 hàm để lấy IP khách truy cập
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// get IP $ip_related_headers = array( 'GD_PHP_HANDLER', 'HTTP_AKAMAI_ORIGIN_HOP', 'HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_FASTLY_CLIENT_IP', 'HTTP_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_INCAP_CLIENT_IP', 'HTTP_TRUE_CLIENT_IP', 'HTTP_X_CLIENTIP', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_X_FORWARDED', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_IP_TRAIL', 'HTTP_X_REAL_IP', 'HTTP_X_VARNISH', 'REMOTE_ADDR', ); foreach ( $ip_related_headers as $header ) : if ( isset( $_SERVER[ $header ] ) ) { $header = $_SERVER[ $header ]; } endforeach; |