现在的位置: 首页 > 综合 > 正文

Drupal专业开发指南 第6章 Drupal 用户(3)

2013年05月29日 ⁄ 综合 ⁄ 共 4277字 ⁄ 字号 评论关闭

提供用户信息分类

           
译者:老葛       
Eskalate
科技公司

 

如果你在http://drupal.org拥有一个帐号,通过登录并点击“my account”链接,接着选择编辑标签(edit tab),你就可以看到提供关于用户信息的分类的效果。除了编辑你的帐号信息比如你的密码以外,你可以在其它分类中你还可以提供你的其它个人信息。在编写此书时,http://drupal.org支持编辑CVS信息、Drupal相关信息、个人信息、工作信息、以及接收新闻通讯的偏好。

 

通过使用profile.module或者用户钩子的分类操作,你可以添加像这些分类一样的信息分类;参看profile.module中的实现。

 

外部登陆

 

Drupal已经内置了对外部认证的支持,通过在一个模块中实现相应的钩子,就可以简单的将外部认证插入到Drupal中。Drupal进行外部认证时所走的流程概貌如图6-6所示。

 

如果没有启用提供外部认证(就是说,实现auth钩子)的模块,Drupal将把所有的用户名当作本地的用户名进行处理。所以joe和joe@example.com都被看做简单的字符串,而没有任何其它特殊含义。然而,如果启用了一个提供外部认证的模块,那么这两个用户名的处理流程就会非常不同了。

 

注意 Drupal在尝试外部认证以前,总是首先尝试以本地用户进行登录。

 

6-6
Drupal的外部登陆流程

 

简单的外部认证

让我们实现一个非常简单的外部认证模块,一个使用简单用户名的公司使用这个模块。假定你的公司只雇用名为Dave的员工,而用户名基于第一个和最后一个名字(姓和名)指定。对于任何以dave开头的用户名都将通过该模块的认证,所以用户davebrown,
davesmith, 和davejones都将能够成功的登录。

 

<?php

// $Id$

/**

* Implementation of hook_auth()

*/

function authdave_auth($username, $pass, $server) {

// Does username begin with 'dave'?

if (substr(drupal_strtolower($username, 0, 4 )) == 'dave') {

// Make a global variable to note that we did the authentication.

global $authdave_authenticated;

$authdave_authenticated = TRUE;

return TRUE;

}

else {

return FALSE;

}

}

 

如果一个用户在users表中不存在对应的记录,那么将会为其创建一个记录。然而,在登录过程中创建的用户没有为其提供e-mail地址,在Drupal默认的本地用户注册时则提供了e-mail地址,如果你的站点需要发送e-mail,那么这样简单的模块就不是一个可行的解决方案。你需要设置users表的mail列,这样你就有了一个与用户相关联的e-mail地址。为了做到这一点,你可以实现用户钩子(hook_user),给出插入操作时的逻辑,这样当插入一个新的用户时就会调用相应的逻辑:

 

 

/**

* Implementation of hook_user()

*/

function authdave_user($op, &$edit, &$account, $category = NULL) {

switch($op) {

case 'insert':

// New user was just added; if we did authentication,

// look up email address of user in a legacy database.

global $authdave_authenticated;

if ($authdave_authenticated) {

$email = mycompany_email_lookup($account->name);

// Set email address in the user table for this user.

db_query("UPDATE {users} SET mail = '%s' WHERE uid = %d", $email,

$account->uid);

}

break;

}

}

 

聪明的读者将会注意到,如果同时启用了Drupal的本地认证和我们的外部认证,那么就没有一种方式来让插入操作下面的代码告诉我们,用户是通过本地认证的还是通过外部认证的;所以我们在这里使用全局变量以指示我们的模块进行了认证。

 

使用提供的服务器进行外部认证

当一个用户使用joe@example.com格式的用户名开始登录时,我们需要依照更多的信息进行处理。Drupal内核包含了drupal.module,它提供了一个XML-RPC客户端,可用于连接到其它服务器上请求认证。例如,在网站http://groups.drupal.org上,你可以使用你在http://drupal.org上的用户名和密码进行登录。下面是我第一次登录时所发生的事情:

 

1.我使用用户名jvandyk@drupal.org和我的密码在groups.drupal.org上登录。、

2.groups.drupal.org检查本地用户数据库并且没有找到我。

3.groups.drupal.org检查authmap,也没能找到我。

4.由于在groups.drupal.org上启用了drupal.module,调用它的auth钩子。

5.
drupal.module向http://drupal.org发送一个XML-RPC请求,并且询问,“在你这里是不是有一个名为jvandyk并且使用这个密码的用户?”

6.
drupal.org回答道,“是的,它是一个热心的用户”。

7.
groups.drupal.org为我在users表中添加一条记录(包括一个本地用户ID),在authmap表中也添加一条记录,这样当我下次登录时,只需要运行步骤1和步骤3就可以了。

 

当提供了一个服务器时,外部登陆的关键点在于authmap表。这个表包含了3个很重要的列:用户ID,外部的用户名,处理认证的模块的名字。在前面的例子中,我的用户ID可能是334,用户名是jvandyk@drupal.org,模块列的值为drupal,这是因为drupal
module对我进行了认证,当我下次登录时仍然由它负责认证我。

 

 

注意 在这里,drupal.org为groups.drupal.org对我进行了认证。但是drupal.org没有将我的e-mail地址提供给groups.drupal.org。和我们本节中的简单外部认证例子一样,如果http://groups.drupal.org的维护者认为users表的mail列都有值的话,那么这将是一个非常愚蠢的想法。这里使用了一个随机生成的密码作为password列的值。

 

下面是drupal.module中auth钩子实现的简化版本,用来说明前面场景所用到的代码:

 

/**

* Implementation of hook_auth().

*/

function drupal_auth($username, $password, $server = FALSE) {

if (!empty($server)) {

// Ask remote server to attempt login for this username and password.

$result = xmlrpc("http://$server/xmlrpc.php", 'drupal.login', $username,

$password);

if ($result === FALSE) { // Authentication failed.

drupal_set_message(t('Error %code: %message', array(

'%code' => xmlrpc_errno(),

'%message' => xmlrpc_error_msg())), 'error');

return FALSE;

}

else {

return $result;

}

}

}

}

 

在认证服务器上(在前面的例子中就是http://drupal.org),为了响应服务器端drupal_auth()发出的XML-RPC请求,运行以下代码:

 

/**

* Callback function from drupal_xmlrpc() for authenticating remote clients.

*

* Remote clients are usually other Drupal instances.

*/

function drupal_login($username, $password) {

if (variable_get('drupal_authentication_service', 0)) {

if ($user = user_load(array(

'name' => $username,

'pass' => $password,

'status' => 1))) {

// Found an unblocked user so return user ID.

return $user->uid;

}

else {

return 0;

}

}

}

 

info钩子

如果你的模块实现了外部认证(也就是说,使用了auth钩子),那么你也应该实现info钩子。这个钩子提供了你模块的名字以及它的验证方法,当其它模块想知道有哪些验证方法可用时使用这一信息。例如,在user.module就用它构建用户登录页面所支持的认证方法列表:

 

/**

* Implementation of hook_info().

*/

function drupal_info($field = 0) {

$info['name'] = 'Drupal';

$info['protocol'] = 'XML-RPC';

if ($field) {

return $info[$field];

}

else {

return $info;

}

}

 

总结

读完本章后,你应该能够

• 理解用户在Drupal内部是如何表示的

• 理解如何使用不同的方式来存储与用户相关的信息

• 使用用户注册过程中的钩子,来获取一个正在注册的用户的更多信息。

• 使用用户登录过程中的钩子,在用户登录时运行你自己的代码

• 理解两种不同的外部认证方式的工作原理


实现你自己的外部认证模块

 

 

注意 更多关于外部认证的信息,参看ldap_integration.module,
pubcookie.module, 和
sxip.module。

 

 

抱歉!评论已关闭.