Cum să validezi un utilizator din afara WordPress/php?
Lucrez la o aplicație AJAX care va fi integrată într-o pagină WordPress. Aplicația AJAC schimbă date cu servlete rulează pe Tomcat. Acum servletele au nevoie de o metodă pentru a determina dacă o cerere vine de la un utilizator autentificat în WordPress. Dacă utilizatorul este logat, servletele trebuie să poată determina ID-ul utilizatorului pentru a interoga baza de date. Dacă utilizatorul nu este logat, cererea va fi respinsă.
Cu alte cuvinte, am nevoie ca un servlet să execute o cerere doar dacă utilizatorul care a inițiat cererea este autentificat în WordPress (versiunea 3.3.x). Atât servletele (Tomcat) cât și WordPress (Apache2) rulează pe aceeași mașină fizică și folosesc aceeași bază de date.
Teoretic, aceasta ar putea fi rezolvată ușor în felul următor:
- În timpul autentificării în WordPress, un token de utilizator este stocat într-o variabilă JavaScript.
- Aplicația AJAC transmite tokenul utilizatorului către servlete la fiecare apel.
- Servletele folosesc tokenul pentru a interoga WordPress dacă este valid (adică dacă utilizatorul este logat) și execută sau resping cererea.
Întrebarea este cum poate fi implementat acest lucru pe partea de WordPress?
Problema care face teoria complicată este faptul că nu am făcut încă programare PHP.
La început m-am gândit să transmit cookie-ul wordpress_logged_in (auth) către servlet și să las servletul să interogheze WordPress dacă cookie-ul auth este încă valid. Dar se pare că acest lucru nu poate fi făcut, deoarece wp_validate_auth_cookie() întotdeauna eșuează, chiar dacă sunt transmise datele cookie ale unui utilizator logat. O altă soluție ar putea fi dezvoltarea unui plugin care să stocheze sessionid-ul și userid-ul într-un tabel, care ar putea fi ușor interogat de servlete. Sau poate există o altă soluție...

WordPress are deja un API integrat prin intermediul unui server XMLRPC. Acest lucru înseamnă că poți face o cerere XMLRPC din aplicația ta Java și să verifici un nume de utilizator/parolă. Din păcate, nu există o modalitate de a autentifica direct prin aceasta în starea sa actuală.
Totuși, este foarte ușor să implementezi propria soluție. Pur și simplu conectează-te la filtrul xmlrpc_methods
și adaugă-ți metoda. Cheia din array pe care o adaugi va fi metoda XMLRPC pe care o apelezi din aplicația ta, iar valoarea va fi funcția apelată de serverul XMLRPC al WordPress.
<?php
add_filter('xmlrpc_methods', 'wpse39662_add_login_method' );
/**
* Filtrează metodele XMLRPC pentru a permite doar verificarea numelui de utilizator/parolă
* pentru un anumit utilizator
*/
function wpse39662_add_login_method( $methods )
{
$methods['wpse39662.login'] = 'wpse39662_check_login';
return $methods;
}
Iar funcția de callback, wpse39662_check_login
, va primi un singur argument, array-ul de date trimise către serverul XMLRPC.
<?php
function wpse39662_check_login( $args )
{
$username = $args[0];
$password = $args[1];
$user = wp_authenticate( $username, $password );
if( is_wp_error( $user ) )
{
return false;
}
return true;
}
Poți găsi toate acestea ca un plugin. Cu acesta instalat și XMLRPC activat pe site-ul tău WordPress, ar trebui să poți face cereri folosind un client XMLRPC (sigur Java are unul).
Iată codul pe care l-am folosit pentru a testa funcționalitatea de mai sus (client XMLRPC în Python).
>>> import xmlrpclib as xmlrpc
>>> s = xmlrpc.ServerProxy('http://wordpress.dev/xmlrpc.php')
>>> s.wpse39662.login('admin', 'password')
True

Mulțumesc! Asta mă aduce cu un pas uriaș înainte! Poate fi realizat același lucru folosind cookie-ul de autentificare al utilizatorului? Ca să nu fie nevoie să stochez și să trimit numele de utilizator/parola prin rețea? Proiectul meu constă într-o aplicație AJAX care este integrată într-o pagină WordPress. Aplicația AJAX apelează un servlet, iar servletul întreabă WordPress dacă utilizatorul este autentificat. Aș putea să transmit numele de utilizator/parola către aplicația AJAX și să le transfer către servlet, dar mă tem că nu ar fi foarte sigur. Așa că am încercat să transmit conținutul cookie-ului de autentificare la wp_validate_auth_cookie(), dar întotdeauna eșuează.

WordPress (în prezent) verifică dacă utilizatorul este încă autentificat prin verificarea unuia dintre cookie-urile pe care le generează la logare. Conținutul acestui cookie este construit prin intermediul unor operații de hashing. Detaliile se găsesc în funcția "wp_generate_auth_cookie" din /wp-includes/pluggable.php:
function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth') {
$user = get_userdata($user_id);
$pass_frag = substr($user->user_pass, 8, 4);
$key = wp_hash($user->user_login . $pass_frag . '|' . $expiration, $scheme);
$hash = hash_hmac('md5', $user->user_login . '|' . $expiration, $key);
$cookie = $user->user_login . '|' . $expiration . '|' . $hash;
return apply_filters('auth_cookie', $cookie, $user_id, $expiration, $scheme);
}
Puteți recrea acest algoritm (folosind această funcție și alte funcții auth_cookie) în codul vostru Java pentru a face aceleași verificări. JS ar putea fi folosit pentru a vă asigura că cookie-ul este trimis către servlet-ul vostru.
Alternativ, XMLRPC ar putea fi o idee bună. Ați putea scrie o nouă metodă (așa cum este explicat într-o altă soluție de aici) pentru a valida cookie-ul de autentificare (în loc să validați numele de utilizator și parola, așa cum se face de obicei).

Obțineți modulul Exec-PHP, apoi creați o pagină WordPress (nu un articol) cu un permalink frumos (http://mysite/user_id/
) și codul din get_current_user_id()
referința API:
<?php
$user_id = get_current_user_id();
if ($user_id == 0) {
echo 'În prezent nu ești autentificat.';
} else {
echo 'Ești autentificat ca utilizator '.$user_id.'.';
}
?>
Apoi puteți extrage cookie-urile pe care clientul vi le trimite și să le includeți într-o cerere GET
pentru http://127.0.0.1/user_id/
. Astfel veți ști dacă utilizatorul este autentificat și care este ID-ul său de utilizator.

Mulțumesc pentru răspuns, problema este că servletele sunt scrise în Java, deci codul PHP nu poate fi executat. Ceea ce caut eu este un fel de interfață externă care să permită unei servlete/Java să comunice cu WordPress/PHP. Cu siguranță există o astfel de interfață disponibilă, dar nu reușesc să o găsesc...

Ah, am înțeles. Poate utilizarea a ceva precum Quercus http://www.caucho.com/resin-3.0/quercus/ ar putea să-ți ofere cele mai bune din ambele lumi?

Mulțumesc, dar Quercus nu este soluția potrivită, deoarece deja am o instalație funcțională WordPress/PHP/Apache și o instalație funcțională servlet/Java/Tomcat. Singurul lucru de care am nevoie acum este o interfață între aceste două, care să permită servletului să verifice dacă un utilizator este autentificat în WordPress (o interfață/protocol/IPC/orice altceva).

Acesta este un plugin WordPress într-un singur fișier care își face treaba:
function yournamespace_validateAuthCookie($cookie, $scheme = 'logged_in') {
return wp_validate_auth_cookie($cookie, $scheme);
}
function yournamespace_new_xmlrpc_methods($methods) {
$methods['yournamespace.validateAuthCookie'] = 'yournamespace_validateAuthCookie';
return $methods;
}
add_filter('xmlrpc_methods', 'yournamespace_new_xmlrpc_methods');
Practic, expune o nouă metodă XML-RPC prin care poți cere WordPress să valideze cookie-ul wordpress_logged_in_...
.
Apoi, va trebui să scrii niște cod pentru a interoga această metodă și pentru a-i transmite valoarea cookie-ului wordpress_logged_in_...
.
Această metodă va returna fie false
(dacă cookie-ul nu este valid) fie ID-ul utilizatorului dacă validarea reușește.
