Registrazione in Drupal da un'applicazione esterna
Domanda
Attualmente sto usando le Services Module e codice personalizzato per cancellare, d'accesso e modificare Drupal utenti da un'applicazione esterna. Posso attualmente il login come utente sulla domanda esterna, ma sono entrato solo nel codice e non il browser vero e proprio. Il che significa che posso eseguire azioni con l'account autenticato nel codice, ma quando ho visitare il mio sito Drupal tramite il browser, non sto loggato. Voglio che i miei utenti di essere connessi in Drupal quando accedono nella mia applicazione esterna. Come posso fare questo?
Soluzione
È possibile utilizzare il modulo di API per scrivere una funzione personalizzata per la convalida di autenticazione. Qualcosa di simile a questo (questo è da Drupal 7, ma per 6 si ha la stessa logica e l'API non è molto diverso). Il codice qui è da un modulo che ho scritto per gli utenti autenticarsi da un IP.Board (un software forum) database:
<?php
/**
* @file
* Allow Drupal 7 to use IP.Board members table for authentication
*
* Some code is based on this nice tutorial http://www.touchnoc.com/node/86
*/
/**
* Alter the user login block form
*/
function ipbridge_form_user_login_block_alter(&$form, &$form_state) {
_ipbridge_user_login_form_alter($form, $form_state);
}
/**
* Alter the user login page
*/
function ipbridge_form_user_login_alter(&$form, &$form_state) {
_ipbridge_user_login_form_alter($form, $form_state);
}
/**
* Change the validate callback
*/
function _ipbridge_user_login_form_alter(&$form, &$form_state) {
$k = array_search('user_login_authenticate_validate', $form['#validate']);
$form['#validate'][$k] = 'ipbridge_authenticate_validate';
}
/**
* Custom validation
*/
function ipbridge_authenticate_validate($form, &$form_state) {
// try normal validation first
user_login_authenticate_validate($form, $form_state);
if ($form_state['uid'] !== FALSE)
return;
// still here? Try to find the user in IP.Board
$name = $form_state['values']['name'];
$pass = $form_state['values']['pass'];
$records = db_select('ibf_members', 'u', array('target' => 'ipb'))
->fields('u', array('member_id', 'name', 'members_pass_hash', 'members_pass_salt', 'email'))
->condition('u.name', $name, '=')
->execute();
if ($records->rowCount() == 1) {
$ipbUser = $records->fetchObject();
// this is how IPB generates the pasword hash
$hash = md5(md5($ipbUser->members_pass_salt) . md5($pass));
if ($hash == $ipbUser->members_pass_hash) {
// based on Drupal's user_external_login_register (that function doesn't set the email address)
$account = user_external_load($name);
if (!$account) {
$userinfo = array(
'name' => $name,
'mail' => $ipbUser->email,
'pass' => user_password(),
'init' => $name,
'status' => 1,
'access' => REQUEST_TIME,
);
try {
$account = user_save(drupal_anonymous_user(), $userinfo);
} catch (Exception $e) {
drupal_set_message(t('Are you trying to login using an IP.Board username that was previously registered in Drupal? Caught exception: ' . $e->getMessage()), 'error');
}
if (!$account) {
drupal_set_message(t("Error saving IPB account."), 'error');
$form_state['uid'] = FALSE;
return;
}
user_set_authmaps($account, array("authname_ipbridge" => $name));
}
$form_state['uid'] = $account->uid;
}
}
}
?>