Можно ли программно авторизовать пользователя без пароля?
Я программно создаю пользователей вручную и хочу авторизовать только что созданного пользователя. WordPress позволяет легко получить хешированный пароль, но не его текстовую версию. Есть ли способ использовать wp_signon() без текстового пароля?
Я нашел одного человека, который утверждает, что сделал это здесь, но у меня это не сработало.
СПАСИБО!

Следующий код выполняет автоматический вход без использования пароля!
// Автоматический вход //
$username = "Admin";
$user = get_user_by('login', $username );
// URL для перенаправления //
if ( !is_wp_error( $user ) )
{
wp_clear_auth_cookie();
wp_set_current_user ( $user->ID );
wp_set_auth_cookie ( $user->ID );
$redirect_to = user_admin_url();
wp_safe_redirect( $redirect_to );
exit();
}

Отлично работает. Достаточно только имени пользователя, причем оно не чувствительно к регистру.

get_user_by()
возвращает false в случае неудачи, поэтому следует проверять на false, а не на объект WP_Error

@Sjoerd Linders, куда можно подключить ваш скрипт, чтобы принудительно требовать подключения пользователя?

wp_set_auth_cookie()
позволяет авторизовать пользователя без необходимости знать его пароль.

Это отлично сработало. Однако, когда я использую это, условная функция is_user_logged_in()
не работает, кажется. Вы знаете, может она проверяет что-то другое, а не куки?

@Emerson - на каком хуке вы выполняете вход пользователя? Это должно происходить до отправки заголовков. Также попробуйте использовать wp_set_current_user
перед входом пользователя.

Вообще-то я не вызывал это из хука. Я просто добавил wp_set_auth_cookie()
в свою функцию входа. Пожалуй, мне нужно переосмыслить этот подход. Я также посмотрю wp_set_current_user и отпишусь. Большое спасибо за вашу помощь в этом вопросе!

Я нашел другое решение здесь, которое использует более правильный подход (по крайней мере, на мой взгляд...).
Нет необходимости устанавливать какие-либо куки, оно использует WordPress API:
/**
* Программный вход пользователя в систему
*
* @param string $username
* @return bool Возвращает true, если вход выполнен успешно; false в противном случае
*/
function programmatic_login( $username ) {
if ( is_user_logged_in() ) {
wp_logout();
}
add_filter( 'authenticate', 'allow_programmatic_login', 10, 3 ); // Подключаем фильтр раньше других обработчиков
$user = wp_signon( array( 'user_login' => $username ) );
remove_filter( 'authenticate', 'allow_programmatic_login', 10, 3 );
if ( is_a( $user, 'WP_User' ) ) {
wp_set_current_user( $user->ID, $user->user_login );
if ( is_user_logged_in() ) {
return true;
}
}
return false;
}
/**
* Callback-функция фильтра 'authenticate', которая авторизует пользователя только по имени.
*
* Чтобы избежать потенциальных уязвимостей безопасности, этот метод должен использоваться только
* в контексте программного входа и должен быть отключен сразу после выполнения.
*
* @param WP_User $user
* @param string $username
* @param string $password
* @return bool|WP_User Возвращает объект WP_User, если пользователь найден, или false в противном случае
*/
function allow_programmatic_login( $user, $username, $password ) {
return get_user_by( 'login', $username );
}
Думаю, код говорит сам за себя:
Фильтр ищет объект WP_User по указанному имени пользователя и возвращает его. Затем вызывается функция wp_set_current_user
с объектом WP_User, возвращенным wp_signon
, проверка с помощью функции is_user_logged_in
, чтобы убедиться, что вход выполнен, и все!
На мой взгляд, это аккуратный и чистый код!

@Shebo Ваш комментарий, кажется, неверен. Первая строка функции проверяет, пуст ли массив $credentials
или нет. Если массив не пуст (как в моем ответе), то значения из массива используются для аутентификации пользователя.

@Mike Вау, как я это пропустил... Моя вина, извини за введение в заблуждение. Я удалю свой первый комментарий, чтобы избежать путаницы. Отличное решение, кстати :)

Это хорошо работает для меня:
clean_user_cache($user->ID); // Очищаем кеш пользователя
wp_clear_auth_cookie(); // Удаляем аутентификационные куки
wp_set_current_user($user->ID); // Устанавливаем текущего пользователя
wp_set_auth_cookie($user->ID, true, false); // Устанавливаем новые аутентификационные куки
update_user_caches($user); // Обновляем кеш пользователя

Эта полезная статья объясняет, почему это необходимо: https://tommcfarlin.com/wordpress-user-caches/

В дополнение к Майку, Полу и Сьёрду:
Для лучшей обработки перенаправлений в login.php
:
//---------------------Автоматический вход--------------------
if(!is_user_logged_in()){
$username = "user1";
if($user=get_user_by('login',$username)){
clean_user_cache($user->ID);
wp_clear_auth_cookie();
wp_set_current_user( $user->ID );
wp_set_auth_cookie( $user->ID , true, false);
update_user_caches($user);
if(is_user_logged_in()){
$redirect_to = user_admin_url();
wp_safe_redirect( $redirect_to );
exit;
}
}
}
elseif('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] == wp_login_url()){
$redirect_to = user_admin_url();
wp_safe_redirect( $redirect_to );
exit;
}
Данный код следует разместить в wp-config.php
сразу после
require_once(ABSPATH . 'wp-settings.php');
Для сведения
На основе приведённого решения я выпустил плагин для поддержания входа пользователя из одного WordPress в другой путём синхронизации данных пользователя и сессии cookie:

Как ни странно, но у меня работает только если сделать редирект и die() после:
clean_user_cache($user->ID);
wp_clear_auth_cookie();
wp_set_current_user( $user_id, $user->user_login );
wp_set_auth_cookie( $user_id, true, true );
update_user_caches( $user );
if ( is_user_logged_in() ) {
$redirect_to = $_SERVER['REQUEST_URI'];
header("location:".$redirect_to );
die();
}

Я считаю, что это правильный путь. Нам следует очистить кеш пользователя и куки. После входа в систему необходимо вызвать хук wp_login
, чтобы другие плагины и основные функции работали совместно.
$user = get_user_by( 'ID', $user_id ); // Получаем объект WP_User по ID пользователя.
// $user = get_user_by( 'email', $email ); // Или получаем по email.
// $user = get_user_by( 'login', $username ); // Или получаем по имени пользователя.
if ( false !== $user ) {
clean_user_cache( $user->ID ); // Очищаем кеш пользователя
wp_clear_auth_cookie(); // Удаляем куки аутентификации
wp_set_current_user( $user->ID, $user->user_login ); // Устанавливаем текущего пользователя
wp_set_auth_cookie( $user->ID ); // Устанавливаем куки аутентификации
update_user_caches( $user ); // Обновляем кеши пользователя
do_action( 'wp_login', $user->user_login, $user ); // Вызываем хук wp_login
}
