【问题标题】:Custom PHP function to verify correct password in Joomla自定义 PHP 函数来验证 Joomla 中的密码是否正确
【发布时间】:2011-11-04 20:04:18
【问题描述】:

我在 Joomla 之外创建了一个可以成功生成 Joomla 密码的脚本:

// I copied the JUserHelper class from Joomla here
$salt = JUserHelper::genRandomPassword(32);
$crypt = JUserHelper::getCryptedPassword($password, $salt);
$psw = $crypt.':'.$salt;

我的问题是,我如何将上面生成的这个新 crypt:salt 与 Joomla 数据库中现有用户的密码进行比较,并知道提供给上述脚本的密码是否是该用户在数据库?

【问题讨论】:

    标签: php joomla passwords


    【解决方案1】:

    在 joomla 3.4.5 中:

    if (!class_exists("JFactory")) {
        define('_JEXEC', 1);
        define('JPATH_BASE', dirname(__FILE__)); // specify path to joomla base directory here
        define('DS', DIRECTORY_SEPARATOR);
    
        require_once ( JPATH_BASE . DS . 'includes' . DS . 'defines.php' );
        require_once ( JPATH_BASE . DS . 'includes' . DS . 'framework.php' );
    
        $mainframe = & JFactory::getApplication('site');
        $mainframe->initialise();
    }
    
    $user = JFactory::getUser(); // or: getUser($id) to get the user with ID $id
    $passwordMatch = JUserHelper::verifyPassword($entered_password, $user->password, $user->id);
    

    【讨论】:

      【解决方案2】:

      编辑:我在之前的回复显示之前发布了这个。

      您总是可以将存储的密码与盐分开,因为它们只是用':'分隔?


      如果页面在 Joomla 框架之外,您将需要包含应该能够通过此完成的框架(reference - 下面的代码块)。如果您在 Joomla 框架内,请跳过此块。但是,我没有测试引用的代码块:

      define( '_JEXEC', 1 );
      
      define( 'DS', DIRECTORY_SEPARATOR );
      define('JPATH_BASE', dirname(__FILE__).DS."..".DS.".." );
      
      require_once ( JPATH_BASE.DS.'includes'.DS.'defines.php' );
      require_once ( JPATH_BASE.DS.'includes'.DS.'framework.php' );
      
      $mainframe =& JFactory::getApplication('site');
      $mainframe->initialise();
      

      在框架中,您需要通过 ID 或用户名查找用户:

      $user  =& JFactory::getUser(username or id goes here);
      

      然后,如果您匹配 $user,您可以简单地访问该用户的密码:

      $user->password;
      

      然后你可以和你的 $psw 比较


      我相信这应该可以帮助你。

      您是希望使用此功能将具有 Joomla 凭据的用户登录到外部站点,还是希望将用户登录到 Joomla 站点?

      【讨论】:

      • 感谢您的代码,我最初只是想在不借用 Joomla 框架的情况下进行密码检查,但我认为这是必要的。这也很有帮助,因为登录用户是我的下一步。
      • 要让用户登录,你需要这样的东西:$credentials['username'] = $user->username; $credentials['password'] = $user->password; $mainframe->login($credentials); 如果你查看 Joomla 身份验证插件的源代码,你会发现它需要凭据在关联数组中。抱歉,我无法正确格式化代码块。
      【解决方案3】:

      一种方法是直接查询 Joomla 数据库以获取用户的(加盐和散列的)密码,然后进行比较。根据我从一些谷歌搜索中看到的内容,我认为下面的查询应该适用于此。我已经在 Wordpress 中完成了这项工作,所以我假设 Joomla 会类似。

      select 'password' from `jos_users` WHERE `username` = "Bob";
      

      【讨论】:

      • 对,但是你如何进行比较呢?它不像比较两个字符串那么简单,因为从一个单词生成的 crypt:salt 字符串每次都会产生不同的字符串,尽管每次都提供相同的密码,所以它永远不会 == 数据库中的内容......我假设有一种方法可以编写一个可以正确进行比较的函数。
      • 如果我理解正确......你不能为用户检索存储的密码,这也会给你盐吗?然后在“:”上拆分字符串,后半部分是盐,前半部分是地穴。然后使用检索到的 salt 值调用上面的代码以生成可能的 crypt,并查看生成的 crypt 值是否与数据库中密码字符串的前面部分匹配。
      • 谢谢,我不知道将数据库存储的盐与我的代码一起使用会产生匹配的密码。
      【解决方案4】:

      很抱歉,上面建议的解决方案是最糟糕的

      因为JUserHelper::genRandomPassword(32)函数是用来生成随机密码的,每次生成时都是不同的密码 因此,与在检查时生成的密码相比,在向用户注册时将在数据库中保存不同的密码,这显然不会以任何方式匹配

      【讨论】:

        【解决方案5】:

        这就是 Joomla 2.5 验证密码的方式

        查看插件文件:\plugins\authentication\joomla\joomla.php

        function onUserAuthenticate($credentials, $options, &$response)
            {
                $response->type = 'Joomla';
                // Joomla does not like blank passwords
                if (empty($credentials['password'])) {
                    $response->status = JAuthentication::STATUS_FAILURE;
                    $response->error_message = JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
                    return false;
                }
        
                // Initialise variables.
                $conditions = '';
        
                // Get a database object
                $db     = JFactory::getDbo();
                $query  = $db->getQuery(true);
        
                $query->select('id, password');
                $query->from('#__users');
                $query->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;
                        if (JFactory::getApplication()->isAdmin()) {
                            $response->language = $user->getParam('admin_language');
                        }
                        else {
                            $response->language = $user->getParam('language');
                        }
                        $response->status = JAuthentication::STATUS_SUCCESS;
                        $response->error_message = '';
                    } else {
                        $response->status = JAuthentication::STATUS_FAILURE;
                        $response->error_message = JText::_('JGLOBAL_AUTH_INVALID_PASS');
                    }
                } else {
                    $response->status = JAuthentication::STATUS_FAILURE;
                    $response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2011-04-25
          • 2013-04-26
          • 2020-01-27
          • 2017-10-06
          • 2017-12-09
          • 2015-01-22
          • 1970-01-01
          • 1970-01-01
          • 2015-06-16
          相关资源
          最近更新 更多