WordPress – Khoá đăng nhập web 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 functions.php lưu lại là xong. File functions.php nằm ở đâu thì bạn có thể đọc qua

Ở đoạn code dưới bạn nên thay đổi email, info@vutruso.com để 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 if ( $datas['tried'] <= 5 ) { thay 5 thành số bạn muốn

add_filter( 'authenticate', 'vutruso_check_attempted_login', 30, 3 );
function vutruso_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  = vutruso_time_to_go( $until );

            wp_mail( 'info@vutruso.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', 'vutruso_login_failed', 10, 1 );
function vutruso_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 vutruso_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;
    }
}

Ghi chú

Hàm đầu tiên, vutruso_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 vutruso_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 vutruso_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

// 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;

Từ khóa
user

Yêu thích Võ thuật và Công nghệ thông tin, thích viết và chia sẽ về 2 lĩnh vực này thế thôi :D

Bài viết liên quan