Cum să verifici username/parola fără a autentifica utilizatorul
Scriu un plugin care creează un endpoint API pentru validarea perechilor username/parolă.
În prezent folosesc wp_signon() pentru a verifica dacă combinația username/parolă funcționează. Funcționează bine când credențialele sunt incorecte deoarece returnează un obiect de eroare. Dar când credențialele sunt corecte, autentifică automat acel utilizator, astfel încât endpoint-ul meu returnează o pagină întreagă.
Codexul momentan nici măcar nu menționează faptul că autentifică automat utilizatorul. De asemenea, nu pare să accepte un parametru pentru a suprima această funcționalitate. Pentru scopurile mele, un simplu boolean ar fi suficient.
ACTUALIZARE: A trebuit să aleg un singur răspuns, dar au existat multe informații utile în celelalte răspunsuri pe care voi încerca să le rezum pe scurt aici...
EXISTĂ o funcție care face exact ce încercam eu să fac:
wp_authenticate($username, $password)TOTUȘI, vine cu un dezavantaj. Va seta automat cookie-urile de autentificare care pot crea probleme într-o situație ca a mea. Așa că aveți grijă. Această funcție nu este momentan în codex.Cea mai bună alegere pentru ceea ce fac eu este
wp_authenticate_username_password($user, $username, $password)deoarece NU setează cookie-urile de autentificare. Această funcție este mai bine documentată, dar detaliul FOARTE important care nu era în codex este că poți transmiteNULLca primul parametru. Acest lucru înseamnă că o poți folosi efectiv pentru a face exact cawp_authenticate()fără să-ți faci griji că cookie-urile se vor strica. Citește documentația pentru a nu fi confuz în privința răspunsului. Returnează fie un obiect WP_User fie un WP_Error (nu un boolean!).
Există o funcție în fișierul user.php din fișierele de bază numită wp_authenticate_username_password care pare a fi ceea ce cauți.
Dacă dorești să eviți să transmiți obiectul $user (probabil ai doar numele de utilizator + parola), atunci trimite null ca prim argument al funcției:
$check = wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' );
Apoi poți verifica simplu rezultatul cu is_wp_error( $check ).
Acest lucru nu face ceea ce sună a face. Este o greșeală comună (pe care am făcut-o și eu). Totuși, tocmai am descoperit o funcție care face exact ceea ce ne dorim! Vezi răspunsul meu...
emersonthis
@kaiser "Hmm". Nu am realizat niciodată că poți folosi NULL ca prim parametru. Asta e bine de știut. Verifică și wp_authenticate() (vezi răspunsul meu). Am găsit-o abia după săptămâni de căutări.
emersonthis
Folosește,
și
Explicație
// obține utilizatorul după login prin numele de utilizator furnizat (input din formular)
$user = get_user_by('login', $username);
// atribuie ID-ul de utilizator pe baza numelui de login
$user_id = $user->ID;
// obține datele utilizatorului prin transmiterea variabilei $user_id către get_userdata
// care returnează obiectul utilizator și o serie de informații legate de utilizator pentru acces
$user_data = get_userdata($user_id);
// atribuie numele de utilizator și parola variabilelor
$user_login = $user_data->user_login;
$user_pass = $user_data->user_pass;
// verifică numele de utilizator/parola față de valorile introduse în formular
if ($user_login = $username && $user_pass = $password) {
// fă ceva...
Note
$usernamear trebui să fie validat implicit ca adevărat, altfel un obiect utilizator nu ar fi fost returnat dacă$usernamefurnizat nu se potrivește cu unul existent în baza de date. Prin urmare, validarea atunci depinde de variabila$passwordcare stochează input-ul din formular furnizat de utilizator.Poate exista o metodă mai eficientă pentru a realiza acest lucru, fie prin scurtarea codului existent, fie prin utilizarea altor funcții API.
ACTUALIZARE
Bazat pe sugestia lui fdsa, ai putea folosi wp_authenticate_username_password în acest mod,
$auth = wp_authenticate_username_password($user, $username, $password);
if (!$auth->user_login = $username && !$auth->user_pass = $password) {
echo 'neautentificat';
} else {
echo 'autentificat';
}
Dar chiar mai bine decât atât,
$auth = wp_authenticate_username_password($user, $username, $password);
if (is_wp_error($auth)) {
echo 'neautentificat';
} else {
echo 'autentificat';
}
Într-adevăr, creditul/răspunsul marcat ar trebui să fie acordat lui fdsa pentru cea mai eficientă metodă prin intermediul (din păcate) a unei funcții nedocumentate din nucleul WP.
Declinare de responsabilitate: Acest răspuns ar trebui doar să arate ce se întâmplă în spatele scenei și nu este menit să fie un exemplu real despre cum să faci lucrurile.
Backtrace
wp_signon() apelează wp_set_auth_cookie(), care la rândul său apelează wp_generate_auth_cookie(). Rezultatul va fi folosit în interiorul setcookie() ca al 2lea argument.
(Non-performant) distracție cu filtre
a.k.a. înșelând WordPress într-un mod greșit.
Apoi ai putea să intervii în filtrul 'auth_cookie' din interiorul wp_generate_auth_cookie() și să-l setezi pur și simplu la null sau la altceva decât valoarea SECURE_AUTH_COOKIE sau AUTH_COOKIE. Acest lucru te va lăsa cu un cookie fără sens, care nu poate efectua autentificarea.
"Ta-da": wp_authenticate($username, $password)
Nu este documentat în codex deloc, dar îl poți căuta pe wpseek.
Face exact ceea ce sugerează. Primește un nume de utilizator și o parolă în text simplu și returnează fie un obiect WP_User fie un WP_Error... și NU autentifică pe nimeni.
Un avertisment important! Următorul cod va returna ÎNTOTDEAUNA true (deoarece funcția returnează un obiect în orice caz):
$auth = ( wp_authenticate($username, $password) ) ? TRUE : FALSE;
Probabil vei dori să faci ceva de genul acesta:
$test_creds = wp_authenticate($username, $pass) ;
$class = get_class($test_creds);
$auth = ( $class == 'WP_User' ) ? TRUE : FALSE ;
Sper că acest lucru îi va fi de folos cuiva.
Poți folosi instanceof sau is_a() pentru a verifica dacă este WP_User. De asemenea, poți pur și simplu să folosești una din funcțiile de mai sus și să elimini filtrul de pe authenticate...
kaiser
Recomand să folosești is_wp_error($auth) care va returna TRUE dacă autentificarea eșuează și FALSE dacă trece de autentificare.
Adam
Încă o observație: Aceasta nu te va loga, dar totuși va lăsa cookie-ul setat, deoarece funcția apelează filtrul `'authenticate`. Dacă alegi această soluție, ar trebui să te asiguri că toate callback-urile filtrului sunt eliminate. Altfel, cerul ar putea să-ți cadă în cap :)
kaiser
E bine de știut. Funcția wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' ); are aceeași problemă? Poți să elaborezi puțin despre "cerul care se prăbușește"? Ce anume se va întâmpla?
emersonthis
Notă: În loc să folosești wp_authenticate, ar fi mai bine să utilizezi user_pass_ok($user_login, $user_pass), care la rândul ei folosește wp_authenticate ca funcție wrapper corectă și returnează true/false. Totuși, după cum a menționat @kaiser, cookie-ul este setat prin filtrul authenticate. Funcția wp_authenticate_username_password nu pare să seteze cookie-ul.
Adam
Conform documentației, wp_authenticate() ÎNTRA-ADEVĂR autentifică utilizatorul dacă credentialele sunt corecte. În mod ciudat, la mine nu funcționează așa.
Gerald Schneider