joomla的用户登陆机制(session)(转)

作者: Administrator
2009-05-25

本文主要讨论Joomla中的用户登陆以及session注册流程与机制。Joomla的登陆过程通过组件com_user,

插件plugin/authenication/joomla.php、plugin/user/joomla.php共同完成,当然底层还
包括application/factory.php、joomla/session/session.php、joomla/session/storage等等诸多部
分共同完成。

首先讲讲登陆的整个过程,用户组件在接受用户登陆请求之后开始发起登陆认证流程autheni
cation过程其实就是向插件plugin/authenication/joomla.php发起认证请求。

function login()
{
// Check for request forgeries
JRequest::checkToken('request') or jexit( 'Invalid Token' );

global $mainframe;

if ($return = JRequest::getVar('return', '', 'method', 'base64')) {
$return = base64_decode($return);
if (!JURI::isInternal($return)) {
$return = '';
}
}

$options = array();
$options['remember'] = JRequest::getBool('remember', false);
$options['return'] = $return;

$credentials = array();
$credentials['username'] = JRequest::getVar('username', '', 'method', 'username');
$credentials['password'] = JRequest::getString('passwd', '', 'post', JREQUEST_ALLOWRAW);

//preform the login action
$error = $mainframe->login($credentials, $options);

if(!JError::isError($error))
{
// Redirect if the return url is not registration or login
if ( ! $return ) {
$return = 'index.php?option=com_user';
}

$mainframe->redirect( $return );
}
else
{
// Facilitate third party login forms
if ( ! $return ) {
$return = 'index.php?option=com_user&view=login';
}

// Redirect to a login form
$mainframe->redirect( $return );
}
}

上面就是登陆组件中的登陆请求部分,重点就是$options以及$credentials,前者记录了一些客户端的行为比如记住我 (remembe me),返回地址,后者类似于一个身份请求令牌,令牌中包括了用户输入的用户名以及密码,这些是要发送给主框架($mainframe)认证的

$mainframe->login($credentials, $options) 发送主框架认证用户信息是否合法

发送给主框架认证用户信息是如何进行的,我们继续深入代码中。

在libraries/joomla/application/application.php中可以看到如下代码:

jimport( 'joomla.user.authentication');
$authenticate = & JAuthentication::getInstance();
$response = $authenticate->authenticate($credentials, $options);

$authenicate->authenticate这个方法就负责认证请求登陆的用户信息,

$response是认证返回信息,很明了。但这一切还不是我想看到的最底层,继续向authenticate函数内部进军,发现了这个函数的全貌:

function authenticate($credentials, $options)
{
// Initialize variables
$auth = false;

// Get plugins
$plugins = JPluginHelper::getPlugin('authentication');

// Create authencication response
$response = new JAuthenticationResponse();

/*
* Loop through the plugins and check of the creditials can be used to authenticate
* the user
*
* Any errors raised in the plugin should be returned via the JAuthenticationResponse
* and handled appropriately.
*/
foreach ($plugins as $plugin)
{
$className = 'plg'.$plugin->type.$plugin->name;
if (class_exists( $className )) {
$plugin = new $className($this, (array)$plugin);
}

// Try to authenticate
$plugin->onAuthenticate($credentials, $options, $response);

// If authentication is successfull break out of the loop
if($response->status === JAUTHENTICATE_STATUS_SUCCESS)
{
if (empty( $response->type )) {
$response->type = isset( $plugin->_name ) ? $plugin->_name : $plugin->name;
}
if (empty( $response->username )) {
$response->username = $credentials['username'];
}

if (empty( $response->fullname )) {
$response->fullname = $credentials['username'];
}

if (empty( $response->password )) {
$response->password = $credentials['password'];
}

break;
}
}
return $response;
}
}

这下已经非常清晰了:

$plugins = JPluginHelper::getPlugin('authentication');

调用所有的authentication类的插件,然后循环认证之前的那个类似令牌的用户输入信息。

foreach ($plugins as $plugin)
{}

换句话说,Joomla可以接受多种认证方式同时进行用户认证,只要有一种认证通过就算通过认证,为什么?请看上文代码,注意那个break;

最后我们看看joomla的认证插件,对于如何用到认证插件进行用户认证的上文已经讲的很清楚了。现在一窥认证的究竟:

plugin/authentication/joomla.php

function onAuthenticate( $credentials, $options, &$response )
{
jimport('joomla.user.helper');
if($options['group']==''){
return false;
}
// Joomla does not like blank passwords
if (empty($credentials['password']))
{
$response->status = JAUTHENTICATE_STATUS_FAILURE;
$response->error_message = 'Empty password not allowed';
return false;
}

// Initialize variables
$conditions = '';

// Get a database object
$db =& JFactory::getDBO();

$query = 'SELECT `id`, `password`, `gid`'
. ' FROM `#__users`'
. ' WHERE username=' . $db->Quote( $credentials['username'] )
;
$db->setQuery( $query );
$result = $db->loadObject();

if($result)
{
$parts = explode( ':', $result->password );
$crypt = $parts[0];
$salt = @$parts[1];
$testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt);

if ($crypt == $testcrypt) {
$user = JUser::getInstance($result->id); // Bring this in line with the rest of the system
$response->email = $user->email;
$response->fullname = $user->name;
$response->status = JAUTHENTICATE_STATUS_SUCCESS;
$response->error_message = '';
} else {
$response->status = JAUTHENTICATE_STATUS_FAILURE;
$response->error_message = 'Invalid password';
}
}
else
{
$response->status = JAUTHENTICATE_STATUS_FAILURE;
$response->error_message = 'User does not exist';
}
}

这里的认证非常明白了,根据用户输入的用户名查出数据库里对应的密码与用户密码匹配,一致就成功,不匹配就认证失败。密码加密方式可参见getCryptedPassword函数提供多种加密方式。

到这里登陆认证的流程基本分析了一遍,那么肯定有人问session在哪里注册了,怎么没见session 的踪迹?让

我们回溯代码到libraries/joomla/application/application.php这个文件,里面有一句异常重要的话:

// Import the user plugin group
JPluginHelper::importPlugin('user');

// OK, the credentials are authenticated. Lets fire the onLogin event
$results = $this->triggerEvent('onLoginUser', array((array)$response, $options));

这里其实trigger了一个事件 onLoginUser,意思是在用户登陆的时候要调用插件提前完成一些操作,session的操作就在这里。插件调用的机制用了PHP里的一个非常出名的设计模式,之前我有介绍《观察者设计模式》查看之前的文章:http://www.joomlar.cn/website/content/view /189/27/

关于session的底层操作下篇文章再详细介绍,joomla提供了两种session存储机制,利用的就是覆写PHP的session类来提供基于数据库以及文件的session存储机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值