Как проверить логин/пароль без авторизации пользователя
Я разрабатываю плагин, который создает API-endpoint для проверки пар логин/пароль.
В настоящее время я использую wp_signon()
для проверки работоспособности комбинации логин/пароль. Это хорошо работает, когда учетные данные неверны, так как возвращается объект ошибки. Но когда учетные данные верны, происходит автоматическая авторизация пользователя, поэтому мой endpoint возвращает целую страницу.
В документации даже не упоминается тот факт, что происходит автоматическая авторизация пользователя. Также не похоже, что есть параметр для отключения этой функциональности. Для моих целей достаточно было бы простого булева значения.
ОБНОВЛЕНИЕ: Мне пришлось выбрать один ответ, но было много полезной информации в нескольких других ответах, которую я кратко попробую обобщить...
СУЩЕСТВУЕТ функция, которая делает именно то, что я пытался сделать:
wp_authenticate($username, $password)
ОДНАКО у нее есть один недостаток. Она автоматически устанавливает куки авторизации, что может создать проблемы в ситуации как у меня. Так что будьте осторожны. Эта функция в настоящее время не документирована в codex.Лучший выбор для моей задачи - это
wp_authenticate_username_password($user, $username, $password)
, потому что она НЕ устанавливает куки авторизации. Эта функция лучше документирована, но ОЧЕНЬ важная деталь, которой не было в codex - это то, что вы можете передатьNULL
в качестве первого параметра. Это означает, что вы можете эффективно использовать ее точно так же, какwp_authenticate()
, не беспокоясь о проблемах с куками. Прочтите документацию, чтобы не запутаться в ответе. Она возвращает либо объект WP_User, либо WP_Error (не булево значение!).

В ядерных файлах WordPress есть функция user.php
под названием wp_authenticate_username_password
, которая, похоже, соответствует тому, что вам нужно.
Если вы хотите избежать передачи объекта $user
(вероятно, у вас есть только имя пользователя и пароль), просто передайте null
в качестве первого аргумента функции:
$check = wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' );
Затем вы можете просто проверить результат с помощью is_wp_error( $check )
.

Это работает не так, как кажется. Обычная ошибка (которую и я совершал). Однако я только что обнаружил функцию, которая делает именно то, что нам нужно! Смотрите мой ответ...

@kaiser "Хм". Я никогда не задумывался, что можно передавать NULL в качестве первого параметра. Полезно знать. Также посмотрите wp_authenticate()
(см. мой ответ). Я нашел её после недель поисков.

Используйте,
и
Объяснение
// получаем пользователя по логину через переданное имя пользователя (ввод из формы)
$user = get_user_by('login', $username);
// присваиваем ID пользователя на основе его логина
$user_id = $user->ID;
// получаем данные пользователя, передавая переменную $user_id в get_userdata
// которая возвращает объект пользователя и множество связанных с ним данных для доступа
$user_data = get_userdata($user_id);
// присваиваем имя пользователя и пароль переменным
$user_login = $user_data->user_login;
$user_pass = $user_data->user_pass;
// проверяем имя пользователя/пароль против переданных значений ввода
if ($user_login = $username && $user_pass = $password) {
// делаем что-то...
Примечания
$username
по умолчанию должен проходить валидацию, иначе объект пользователя не был бы возвращен, если переданный$username
не соответствует существующему в базе данных. Таким образом, валидация зависит от переменной$password
, которая хранит ввод пароля, предоставленный пользователем.Может существовать более эффективный способ достичь этого, либо сократив существующий код, либо используя другие API-функции.
ОБНОВЛЕНИЕ
Следуя предложению fdsa, вы можете использовать wp_authenticate_username_password
следующим образом:
$auth = wp_authenticate_username_password($user, $username, $password);
if (!$auth->user_login = $username && !$auth->user_pass = $password) {
echo 'не аутентифицирован';
} else {
echo 'аутентифицирован';
}
Но еще лучше:
$auth = wp_authenticate_username_password($user, $username, $password);
if (is_wp_error($auth)) {
echo 'не аутентифицирован';
} else {
echo 'аутентифицирован';
}
По праву, заслуга/отмеченный ответ должна принадлежать fdsa за наиболее эффективный метод с использованием (к сожалению) недокументированной функции ядра WP.

Отказ от ответственности: Этот ответ просто показывает, что происходит за кулисами и не является реальным примером того, как следует делать вещи.
Трассировка вызовов
wp_signon()
вызывает wp_set_auth_cookie()
, который затем вызывает wp_generate_auth_cookie()
. Результат будет использован внутри setcookie()
в качестве второго аргумента.
(Неоптимальные) игры с фильтрами
или как обмануть WordPress неправильным способом.
Вы можете перехватить фильтр 'auth_cookie'
внутри wp_generate_auth_cookie()
и просто установить его значение в null или что-то отличное от SECURE_AUTH_COOKIE
или AUTH_COOKIE
. Это оставит вам бесполезную куку, которая не сможет выполнить вход.

"Та-да": wp_authenticate($username, $password)
Этой функции нет в кодексе, но её можно найти на wpseek.
Она делает именно то, что кажется. Принимает имя пользователя и пароль в открытом виде, а возвращает либо объект WP_User
, либо WP_Error
... и при этом НЕ входит в систему.
Одно предупреждение! Следующий код ВСЕГДА будет возвращать true (поскольку функция в любом случае возвращает объект):
$auth = ( wp_authenticate($username, $password) ) ? TRUE : FALSE;
Вероятно, вам нужно сделать что-то вроде этого:
$test_creds = wp_authenticate($username, $pass) ;
$class = get_class($test_creds);
$auth = ( $class == 'WP_User' ) ? TRUE : FALSE ;
Надеюсь, это кому-то поможет.

Вы можете использовать instanceof
или is_a()
для проверки на WP_User
. Также можно просто использовать одну из вышеуказанных функций и удалить фильтр на authenticate
...

Рекомендую использовать is_wp_error($auth)
, который вернет TRUE
при неудачной аутентификации и FALSE
при успешной.

Еще одно замечание: это не выполнит вход в систему, но cookie останется установленным, так как функция вызывает фильтр `'authenticate`. Если вы выберете это решение, вы должны убедиться, что все callback-функции фильтра удалены. Иначе небо может упасть вам на голову :)

Хорошо знать. У wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' );
такая же проблема? Можешь немного подробнее рассказать о "небе, падающем вниз"? Что именно пойдет не так?

Примечание: Вместо использования wp_authenticate
лучше использовать user_pass_ok($user_login, $user_pass)
, который в свою очередь использует wp_authenticate
как правильную обёрточную функцию, возвращающую true/false
. Однако, как сказал @kaiser, куки устанавливаются через фильтр authenticate
. Функция wp_authenticate_username_password
, судя по всему, не устанавливает куки.

Согласно документации, wp_authenticate()
ДЕЙСТВИТЕЛЬНО авторизует пользователя, если учетные данные верны. Странно, но у меня это не работает.
