Как проверить логин/пароль без авторизации пользователя
Я разрабатываю плагин, который создает 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 ).
Это работает не так, как кажется. Обычная ошибка (которую и я совершал). Однако я только что обнаружил функцию, которая делает именно то, что нам нужно! Смотрите мой ответ...
emersonthis
@kaiser "Хм". Я никогда не задумывался, что можно передавать NULL в качестве первого параметра. Полезно знать. Также посмотрите wp_authenticate() (см. мой ответ). Я нашел её после недель поисков.
emersonthis
Используйте,
и
Объяснение
// получаем пользователя по логину через переданное имя пользователя (ввод из формы)
$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...
kaiser
Рекомендую использовать is_wp_error($auth), который вернет TRUE при неудачной аутентификации и FALSE при успешной.
Adam
Еще одно замечание: это не выполнит вход в систему, но cookie останется установленным, так как функция вызывает фильтр `'authenticate`. Если вы выберете это решение, вы должны убедиться, что все callback-функции фильтра удалены. Иначе небо может упасть вам на голову :)
kaiser
Хорошо знать. У wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' ); такая же проблема? Можешь немного подробнее рассказать о "небе, падающем вниз"? Что именно пойдет не так?
emersonthis
Примечание: Вместо использования wp_authenticate лучше использовать user_pass_ok($user_login, $user_pass), который в свою очередь использует wp_authenticate как правильную обёрточную функцию, возвращающую true/false. Однако, как сказал @kaiser, куки устанавливаются через фильтр authenticate. Функция wp_authenticate_username_password, судя по всему, не устанавливает куки.
Adam
Согласно документации, wp_authenticate() ДЕЙСТВИТЕЛЬНО авторизует пользователя, если учетные данные верны. Странно, но у меня это не работает.
Gerald Schneider