Как перенаправить пользователя после ввода неправильного пароля?
Я использую wp_login_form()
для отображения формы входа в диалоговом окне jQuery.
Если пользователь вводит неправильный пароль, его перенаправляет в панель администратора. Я не хочу этого. Есть ли способ уведомить пользователя о том, что он ввел неправильный пароль и при этом остаться на той же странице?
До появления wp_login_form()
я использовал плагин. Я надеюсь, что смогу обойтись без использования плагина для этого.
Мой код:
wp_login_form( array(
'label_remember' => __( 'Запомнить меня' ),
'label_log_in' => __( 'Войти' )
) );

Я попал сюда из Google. Но ответ меня не удовлетворил. Я искал некоторое время и нашел лучшее решение.
Добавьте это в ваш файл functions.php:
add_action( 'wp_login_failed', 'my_front_end_login_fail' ); // хуки для неудачной попытки входа
function my_front_end_login_fail( $username ) {
$referrer = $_SERVER['HTTP_REFERER']; // получаем URL, откуда пришел запрос
// если есть корректный referrer и это не стандартный экран входа или админка
if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
wp_redirect( $referrer . '?login=failed' ); // добавляем параметр login=failed к URL для дальнейшего использования в теме
exit;
}
}

Спасибо, Алексей, я протестирую это (пока я все еще использую плагин)

Решение Алексея работает при вводе неверных учетных данных, но, к сожалению, не срабатывает, когда пользователь забывает ввести имя пользователя или пароль. Похоже, Wordpress даже не пытается войти в систему в этом случае, поэтому действие wp_login_failed не выполняется.

Я бы использовал wp_get_referer() здесь, чтобы сэкономить время: http://codex.wordpress.org/Function_Reference/wp_get_referer

Текущий метод, который я использую для решения всех описанных здесь проблем, отлично работает даже с пустыми именем пользователя/паролем и не зависит от JavaScript (хотя JS может быть полезен в дополнение к этому).
add_action( 'wp_login_failed', 'custom_login_failed' );
function custom_login_failed( $username )
{
$referrer = wp_get_referer();
if ( $referrer && ! strstr($referrer, 'wp-login') && ! strstr($referrer,'wp-admin') )
{
wp_redirect( add_query_arg('login', 'failed', $referrer) );
exit;
}
}
Ключевым моментом является этот фильтр для изменения обработки пустого имени пользователя/пароля:
add_filter( 'authenticate', 'custom_authenticate_username_password', 30, 3);
function custom_authenticate_username_password( $user, $username, $password )
{
if ( is_a($user, 'WP_User') ) { return $user; }
if ( empty($username) || empty($password) )
{
$error = new WP_Error();
$user = new WP_Error('authentication_failed', __('<strong>ОШИБКА</strong>: Неверное имя пользователя или пароль.'));
return $error;
}
}
Вы можете пойти дальше и полностью заменить wp-login.php, перенаправляя пользователей на вашу собственную страницу входа и используя эту страницу также для перенаправления при неудачной попытке входа. Полный код:
/**
* Действия для кастомной страницы входа
*/
// Изменяем URL входа по всему сайту на кастомную страницу входа
add_filter( 'login_url', 'custom_login_url', 10, 2 );
// Перенаправляем wp-login на кастомную страницу входа с кастомными переменными запроса при необходимости
add_action( 'login_head', 'custom_redirect_login', 10, 2 );
// Обновляем обработчик неудачного входа для отправки пользователя обратно на кастомную форму с переменной запроса
add_action( 'wp_login_failed', 'custom_login_failed', 10, 2 );
// Обновляем аутентификацию для возврата ошибки, если одно или оба поля пусты
add_filter( 'authenticate', 'custom_authenticate_username_password', 30, 3);
// Автоматически добавляем форму входа на страницу "login"
add_filter( 'the_content', 'custom_login_form_to_login_page' );
/**
* Функции для кастомной страницы входа
*/
function custom_login_url( $login_url='', $redirect='' )
{
$page = get_page_by_path('login');
if ( $page )
{
$login_url = get_permalink($page->ID);
if (! empty($redirect) )
$login_url = add_query_arg('redirect_to', urlencode($redirect), $login_url);
}
return $login_url;
}
function custom_redirect_login( $redirect_to='', $request='' )
{
if ( 'wp-login.php' == $GLOBALS['pagenow'] )
{
$redirect_url = custom_login_url();
if (! empty($_GET['action']) )
{
if ( 'lostpassword' == $_GET['action'] )
{
return;
}
elseif ( 'register' == $_GET['action'] )
{
$register_page = get_page_by_path('register');
$redirect_url = get_permalink($register_page->ID);
}
}
elseif (! empty($_GET['loggedout']) )
{
$redirect_url = add_query_arg('action', 'loggedout', custom_login_url());
}
wp_redirect( $redirect_url );
exit;
}
}
function custom_login_failed( $username )
{
$referrer = wp_get_referer();
if ( $referrer && ! strstr($referrer, 'wp-login') && ! strstr($referrer, 'wp-admin') )
{
if ( empty($_GET['loggedout']) )
wp_redirect( add_query_arg('action', 'failed', custom_login_url()) );
else
wp_redirect( add_query_arg('action', 'loggedout', custom_login_url()) );
exit;
}
}
function custom_authenticate_username_password( $user, $username, $password )
{
if ( is_a($user, 'WP_User') ) { return $user; }
if ( empty($username) || empty($password) )
{
$error = new WP_Error();
$user = new WP_Error('authentication_failed', __('<strong>ОШИБКА</strong>: Неверное имя пользователя или пароль.'));
return $error;
}
}
function custom_login_form_to_login_page( $content )
{
if ( is_page('login') && in_the_loop() )
{
$output = $message = "";
if (! empty($_GET['action']) )
{
if ( 'failed' == $_GET['action'] )
$message = "Возникла проблема с вашим именем пользователя или паролем.";
elseif ( 'loggedout' == $_GET['action'] )
$message = "Вы вышли из системы.";
elseif ( 'recovered' == $_GET['action'] )
$message = "Проверьте свою электронную почту для получения ссылки подтверждения.";
}
if ( $message ) $output .= '<div class="message"><p>'. $message .'</p></div>';
$output .= wp_login_form('echo=0&redirect='. site_url());
$output .= '<a href="'. wp_lostpassword_url( add_query_arg('action', 'recovered', get_permalink()) ) .'" title="Восстановить пароль">Забыли пароль?</a>';
$content .= $output;
}
return $content;
}
Настройте и добавьте это, чтобы добавить свой логотип на страницу wp-login для восстановления пароля:
// вызываем только на странице входа
add_action( 'login_enqueue_scripts', 'custom_login_css', 10 );
function custom_login_css() { wp_enqueue_style( 'custom_login_css', get_template_directory_uri() .'/library/css/login.css', false ); }
// изменяем ссылку логотипа с wordpress.org на ваш сайт
add_filter( 'login_headerurl', 'custom_login_logo_url' );
function custom_login_logo_url() { return home_url(); }
// изменяем alt-текст логотипа на название вашего сайта
add_filter( 'login_headertitle', 'custom_login_title' );
function custom_login_title() { return get_option('blogname'); }
CSS для логотипа входа:
.login h1 a {
background: url(../images/login-logo.png) no-repeat top center;
width: 274px;
height: 63px;
text-indent: -9999px;
overflow: hidden;
padding-bottom: 15px;
display: block;
}
РЕДАКТИРОВАНИЕ: Я только что реализовал это на другом сайте с нуля и обнаружил, что вышеуказанный "шаг дальше" является более полным, исправил небольшие синтаксические ошибки в "add_actions". Добавил некоторые комментарии и метод для автоматического добавления формы входа на страницу входа без отдельного файла шаблона. Метод формы входа должен работать в большинстве случаев, так как он привязан к "the_content", он может вызвать проблему, если у вас более одного цикла на странице входа, в этом случае просто используйте шаблон page-login.php.

Спасибо, я посмотрю на это (и проверю, смогу ли я заставить это работать вместе со сторонними сервисами входа, такими как Twitter и FB)

Джейк - это хорошее комплексное решение. Спасибо, что поделились. +1

Это по сути встроено в плагин под названием Sewn In Template Login, довольно полный, небольшой плагин. https://wordpress.org/plugins/sewn-in-template-log-in/

wp_login_form()
создаёт форму с атрибутом action равным site_url/wp-login.php
, что означает, что при нажатии кнопки отправки форма передаётся на site_url/wp-login.php
, который игнорирует redirect_to при ошибках (например, неправильный пароль). Поэтому в вашем случае либо вернитесь к использованию плагина, либо воссоздайте весь процесс авторизации, чтобы получить контроль над ошибками. Посмотрите Проверка правильности имени пользователя в кастомной форме входа, где рассмотрен очень похожий вопрос.

Решение для замечания Щепана Холышевского о пустых полях в принятом решении. Следующий jQuery код предотвратит переход на стандартную страницу wp-login: (добавьте в шаблон страницы входа или footer.php)
jQuery("#loginform-custom").submit(function(){
var isFormValid = true;
jQuery("input").each(function()
{
if (jQuery.trim($(this).val()).length == 0){
jQuery(this).addClass("submit_error");
isFormValid = false;
}
else {
jQuery(this).removeClass("submit_error");
}
});
return isFormValid;
});

Следующее решение сработало у меня. Оба хука находятся в функции wp_authenticate
внутри файла wp-includes/pluggable.php
.
- Проверка через фильтр
authenticate
, заполнены ли поля логина и пароля в форме входа.
function wpse_15633_redirectMissingDataLoginForm($user, $username, $password)
{
$errors = [];
empty(trim($password)) && $errors[] = 'password_empty';
empty(trim($username)) && $errors[] = 'username_empty';
if (!empty($errors)) {
$redirect_url = add_query_arg([
'errors' => join(',', $errors),
], site_url('login', 'login_post'));
if (wp_safe_redirect($redirect_url)) {
exit;
}
}
return $user;
}
add_filter('authenticate', 'wpse_15633_redirectMissingDataLoginForm', 10, 3);
- Проверка через действие
wp_login_failed
, не удалась ли аутентификация введённого имени пользователя и пароля.
function wpse_15633_redirectFailedLoginForm($username, $error)
{
$redirect_url = add_query_arg([
'errors' => $error->get_error_code(),
], site_url('login', 'login_post'));
if (wp_safe_redirect($redirect_url)) {
exit;
}
}
add_action('wp_login_failed', 'wpse_15633_redirectFailedLoginForm', 10, 2);

Дополнение к ответу Алексея. Вы можете добавить функцию jQuery, чтобы проверить, что одно из полей не пустое. Таким образом, форма не отправится, пока не будет данных для проверки, что предотвратит перенаправление WordPress на страницу /wp-login.php.
<script>
$("#wp-submit").click(function() {
var user = $("input#user_login").val();
if (user == "") {
$("input#user_login").focus();
return false;
}
});
</script>
Всё ещё не уверен, как исправить аспект с забытым паролем

Пожалуйста, учтите, что WordPress загружает jQuery в режиме "No Conflict". Псевдоним $
не работает.

Дополняя полезный ответ @alexey и предлагая решение для упомянутой другими проблемы.
Его код для добавления в файл functions.php:
add_action( 'wp_login_failed', 'my_front_end_login_fail' ); // хук для неудачной попытки входа
function my_front_end_login_fail( $username ) {
$referrer = $_SERVER['HTTP_REFERER']; // откуда пришел POST-запрос?
// если есть валидный реферер и это не стандартный экран входа
if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
wp_redirect( $referrer . '?login=failed' ); // добавляем параметр (login=failed) к URL для использования в теме
exit;
}
}
Однако, как отмечали другие, если поля пустые, WordPress не проводит валидацию, и пользователи всё равно попадают на экран входа в админку.
Чтобы это обойти, я добавляю скрипт сразу после создания формы, который добавляет атрибут required
к полям ввода, чтобы браузер останавливал отправку формы с пустыми полями.
На странице с вашей формой:
<?php
$args = array(
'form_id' => 'YOUR-FORM-NAME',
);
wp_login_form( $args );
?>
<script>
if(jQuery('form#YOUR-FORM-NAME').length) {
jQuery('form#YOUR-FORM-NAME input').each(function() {
jQuery(this).attr("required", true);
});
}
</script>

jQuery("#loginform-custom").submit(function(){
var isFormValid = true;
jQuery("input").each(function()
{
if (jQuery.trim($(this).val()).length == 0){
jQuery(this).addClass("submit_error");
isFormValid = false;
}
else {
jQuery(this).removeClass("submit_error");
}
});
return isFormValid;
});
