Drupal 6.x 和 5.x 的 HOOK 函数和参数表有很大的差别,所以建议大家多看看 Drupal API手册。后来绕了一大圈发现 Drupal 6.x 的默认模组 (modules) 里面,有一个叫 OpenId 的模组可以实现这个功能。当然,我们的外部身份验证需求通常不唯一的,比如可能是 Discuz! 论坛或者你当前站点的身份验证,制定一个外部身份验证模组正是我们今天的题目解决的问题。
首先我们做开发一个模组的例行工作
exuser.info- (模组信息)
name = External authenticate
description = Allows users to log using external authenticate.
package = Bun Drupal
version = 0.1
core = 6.x
exuser.install- (模组安装脚本)
<?php
/**
* Implementation of hook_install().
*/
function exuser_install() {
// Create table.
drupal_install_schema('exuser');
}
/**
* Implementation of hook_uninstall().
*/
function exuser_uninstall() {
// Remove table.
drupal_uninstall_schema('exuser');
}
/**
* Implementation of hook_schema().
*/
function exuser_schema() {
$schema['exuser_authenticate'] = array(
'description' => 'Stores eway users',
'fields' => array(
'uid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'name' => array(
'type' => 'char',
'length' => 11,
'not null' => TRUE,
),
),
'primary key' => array('uid'),
);
return $schema;
}
这个脚本告诉 Drupal 安装的时候会生成一个数据表 exuser_authenticate,里面的两个字段是 Drupal 的 uid 和你的身份验证的用户名,因为每个验证用户都需要在 Drupal 的 users 表产生一个用户记录,那么 exuser_authenticate 就是一个对照表
exuser.module- (模组脚本)
<?php
/**
* Implementation of hook_form_alter.
*/
function exuser_form_alter(&$form, $form_state, $form_id)
{
if ($form_id == 'user_login_block' || $form_id == 'user_login') {
drupal_add_js(drupal_get_path('module', 'exuser') .'/exuser.js');
$form['external_identifier'] = array(
'#type' => 'checkbox',
'#title' => '外部登录',
'#weight' => -3,
);
$form['external_name'] = array(
'#type' => 'textfield',
'#title' => '外部用户名',
'#size' => 15,
'#maxlength' => 11,
'#required' => true,
'#weight' => -2,
);
$form['external_pass'] = array(
'#type' => 'password',
'#title' => '外部密码',
'#size' => 15,
'#required' => true,
'#weight' => -1,
);
if ($form_id == 'user_login') {
$form['external_name']['#description'] = '请输入外部用户名';
$form['external_pass']['#description'] = '请输入外部密码';
unset($form['external_name']['#size'], $form['external_pass']['#size']);
}
if (isset($form_state['post']['external_identifier'])) {
$form['name']['#required'] = false;
$form['pass']['#required'] = false;
unset($form['#submit']);
$form['#validate'] = array('exuser_login_validate');
} else {
$form['external_name']['#required'] = false;
$form['external_pass']['#required'] = false;
}
}
}
function exuser_login_validate($form, &$form_state)
{
$external_name = $form_state['values']['external_name'];
$external_pass = $form_state['values']['external_pass'];
// TODO使用 $external_name 和 $external_pass 进行外部验证函数,返回 true 或 false
$result = true;
if ($result) {
exuser_authenticate_complete($external_name, $form_state['values']);
} else {
drupal_set_message('用户登录失败', 'error');
}
}
function exuser_authenticate_complete($identity, $values)
{
$account = exuser_external_load($identity);
if (isset($account->uid)) {
user_external_login($account, $values);
} else {
// 构造注册表单
$form_state = array();
$form_state['redirect'] = NULL;
$form_state['values']['name'] = $identity;
$form_state['values']['mail'] = $identity . '@mobile';
$form_state['values']['pass'] = user_password();
$form_state['values']['status'] = true;
$form_state['values']['response'] = $response;
$form_state['values']['auth_openid'] = $identity;
$form = drupal_retrieve_form('user_register', $form_state);
drupal_prepare_form('user_register', $form, $form_state);
drupal_validate_form('user_register', $form, $form_state);
if (form_get_errors()) {
drupal_set_message('用户注册失败', 'error');
$destination = drupal_get_destination();
unset($_REQUEST['destination']);
drupal_goto('user/register', $destination);
} else {
// 注册成功
$account = user_save('', $form_state['values']);
if (!$account) {
drupal_set_message('保存用户失败', 'error');
drupal_goto();
}
// 插入用户名与 uid 对照表
exuser_external_save($account, $identity);
user_external_login($account);
}
drupal_redirect_form($form, $form_state['redirect']);
}
}
function exuser_external_load($identity)
{
$result = db_query("SELECT uid FROM {exuser_authenticate} WHERE name = '%s'", $identity);
if ($user = db_fetch_array($result)) {
return user_load($user);
} else {
return false;
}
}
function exuser_external_save($account, $identity)
{
db_query("INSERT INTO {exuser_authenticate} (`uid`, `name`) VALUES (%d, '%s')", $account->uid, $identity);
}
调用外部验证的时候,把 // TODO 那行改成你的验证方法就可以了。
在 user_login 和 user_login_block 的页面上会调用一个 JS 用来切换登录模式
exuser.js- (模组 Javascript)
Drupal.behaviors.exuser=function(context){
var$loginElements=$("#edit-name-wrapper, #edit-pass-wrapper");
var$ewayLoginElements=$("#edit-external-name-wrapper, #edit-external-pass-wrapper");
var$identifierElement=$('#edit-external-identifier');
varsetStatus=function(e){
if($identifierElement.attr('checked')){
$loginElements.hide();
$ewayLoginElements.show();
}else{
$ewayLoginElements.hide();
$loginElements.show();
}
};
setStatus();
$identifierElement.click(setStatus);
};