Поддержка Проблемы и решения Хук при отправке формы с паролем в постах

  • Доброго дня
    Дело в том, что нужно ограничить количество попыток ввода пароля в постах, защищенных паролем. Пытался найти подобный плагин, но безрезультатно. Нашел много плагинов, которые ограничивают количество попыток ввода пароля на странице авторизации, а вот для защищенных паролем постов ничего подобного не смог найти. Поэтому буду пытаться делать сам.
    Не подскажете хук, за который можно зацепиться при отправке формы ввода пароля в постах, защищенных паролем ?
    Буду рад любому совету.
    Спасибо

Просмотр 14 ответов — с 1 по 14 (всего 14)
  • Хук то https://developer.wordpress.org/reference/functions/post_password_required/ но вот как его использовать? Ввод пароля обрабатывается в wp-login.php на postpass просто установкой куки, которая в post_password_required и проверяется.

    Модератор Sergey Biryukov

    (@sergeybiryukov)

    Live and Learn

    Ввод пароля обрабатывается в wp-login.php на postpass

    Вот туда и можно подключиться с помощью действия login_form_postpass, перехватив управление чуть раньше.

    А количество попыток сохранять в метаданных пользователя, примерно так:

    
    add_action( 'login_form_postpass', function() {
    	$max_postpass_attempts = 3;
    
    	$user_id           = get_current_user_id();
    	$postpass_attempts = (int) get_user_meta( $user_id, 'postpass_attempts', true );
    
    	if ( $postpass_attempts < $max_postpass_attempts ) {
    		update_user_meta( $user_id, 'postpass_attempts', ++$postpass_attempts );
    	} else {
    		wp_die( 'Число попыток ввода пароля исчерпано.' );
    	}
    });
    
    Автор Dmitry Kohan

    (@dmay1989)

    @sergeybiryukov , спасибо большое.
    Но как быть если пользователь не авторизован ?

    Автор Dmitry Kohan

    (@dmay1989)

    Появилась идея сделать следующее — если пользователь не авторизован и пост защищен паролем, перенаправлять пользователя на страницу авторизации

    add_action('template_redirect', 'post_password_result');  
    function post_password_result() {
        if( ! is_user_logged_in() && post_password_required() ) {
            wp_redirect( home_url('/wp-login.php') );
            exit;
        }
    }

    Но редирект срабатывает всегда, не получается добиться, чтобы post_password_required() работала должным образом. Не подскажете, где я ошибся в коде выше ?

    Автор Dmitry Kohan

    (@dmay1989)

    Проблему, описанную мной в последнем сообщении, решил добавлением условия is_singular('post')

    Автор Dmitry Kohan

    (@dmay1989)

    Но как решить начальный вопрос с количеством попыток ввода пароля, если пользователь не авторизован и нет возможности регистрации ?

    Но как решить начальный вопрос с количеством попыток ввода пароля, если пользователь не авторизован и нет возможности регистрации ?

    если только делать привязку к кукам или АйПи .

    Автор Dmitry Kohan

    (@dmay1989)

    если только делать привязку к кукам или АйПи .

    т.е. если делать привязку к IP, то получается примерно следующий алгоритм:
    пользователь ввел пароль, сохраняю нового пользователя если такового нет с логином IP, пароль рандомный — с помощью wp_create_user(), затем сохраняю в метаданные количество попыток и время попытки ввода пароля, и затем при след попытке проверяю количество попыток — и если количество попыток меньше разрешенного — форма отправляется; если же попытки превышают лимит, то мониторю время следующей попытки с временем из БД — если временной промежуток истек, удаляю количество попыток из БД и ввод пароля снова будет разрешен.
    Примерно правильно ? (буду пробовать)

    Ну как вариант, правда по мне не очень. Можно посмотреть код https://wordpress.org/plugins/limit-login-attempts-reloaded/ — там в options хранятся нарушители.

    Решил пока остановиться на этом варианте — если пользователь не авторизован и пост защищен паролем, перенаправлять пользователя на страницу авторизации:

    add_action('template_redirect', 'post_password_result');  
    function post_password_result() {
        if( ! is_user_logged_in() && is_singular('post') && post_password_required() ) {
            wp_redirect( home_url('/wp-login.php') );
            exit;
        }
    }

    Но вот вопрос, а как направить пользователя после успешного входа не в админку, а на страницу поста с паролем, с которого он пришел на wp-login.php ?

    @dmay1989 вроде работает

    add_action('template_redirect', 'post_password_result');  
    function post_password_result() {
        
        if( ! is_user_logged_in() && is_singular('post') && post_password_required() ) {
            global $post;
            $redirect = home_url() . '/wp-login.php?redirect_to=' . $post->post_name;
            wp_redirect( $redirect );
            exit;
        }
    }
    
    add_filter( 'login_redirect', 'my_login_redirect', 10, 3 );
    
    /**
     * Redirect user after successful login.
     *
     * @param string $redirect_to URL to redirect to.
     * @param string $request URL the user is coming from.
     * @param object $user Logged user's data.
     * @return string
     */
    function my_login_redirect( $redirect_to, $request, $user ) {
        
            if ($redirect_to) {
                return $redirect_to;
            } 
            
            return home_url();
    
    }

    @igor-san , спасибо огромное. У меня получилось реализовать только наполовину — через транзитные опции и направлять пользователя на страницу предшествующую посту с паролем. Ваш вариант рабочий на 100% и в разы проще ! если вдруг будет интересно — опубликую, хотя этот мой код уже неуместен после Вашей публикации

    add_action('template_redirect', 'post_password_result');  
    function post_password_result() {
        if( ! is_user_logged_in() && is_singular('post') && post_password_required() ) {
            if( $return_url = wp_get_referer() ){
               // Запись в транзитный кэш на 1 час
    	       set_transient( 'post_password_referer', $return_url, 1 * HOUR_IN_SECONDS );
            }
            wp_redirect( home_url('/wp-login.php') );
            exit;
        }
    }
    
    add_filter( 'login_redirect', 'my_login_redirect', 10, 3 );
    function my_login_redirect( $redirect_to, $request, $user ) {
    
    	if ( isset( $user->roles ) && is_array( $user->roles ) ) {
    
    		if ( in_array( 'administrator', $user->roles ) ) {
    			return $redirect_to;
    		}
    		else {
    	          $post_password_referer = get_transient( 'post_password_referer' );
    	          if ( $post_password_referer !== false )
    			return $post_password_referer;
                       else
                            return home_url();
    		}
    	}
    	else {
    		return $redirect_to;
    	}
    }
    Модератор Sergey Biryukov

    (@sergeybiryukov)

    Live and Learn

    Думаю, код можно ещё немного упростить:

    
    add_action( 'template_redirect', 'post_password_result' );  
    function post_password_result() {
    	if ( ! is_user_logged_in() && is_singular( 'post' ) && post_password_required() ) {
    		wp_redirect( wp_login_url( get_permalink() ) );
    		exit;
    	}
    }
    

    Если пользователь не авторизован и пытается просмотреть защищённую паролем запись — перенаправляем на страницу логина, а после успешного входа — на запись.

    Функция my_login_redirect(), если я правильно понял задачу, здесь особо не нужна: поскольку адрес указан явно, перенаправление на запись будет происходить и без неё. Она могла бы пригодиться, если бы требовались ещё какие-то дополнительные условия.

    Спасибо огромное за помощь и советы, всё работает!

Просмотр 14 ответов — с 1 по 14 (всего 14)