如何在脚本中创建新的Joomla用户账户?

22
我们正在为Joomla创建一个XML API,允许合作伙伴站点在我们的网站上为其用户创建新帐户。
我们已经创建了一个独立的PHP脚本来处理和验证API请求,但现在我们需要实际创建新帐户。我们最初考虑的是通过CURL调用来提交注册表单,但我们意识到用户令牌存在问题。是否有另一种干净的方法可以创建用户帐户,而不必深入Joomla内部?如果我们确实需要进行一些修改,那么最好的方法是什么?
12个回答

18

为了保证密码安全,建议使用Joomla内部类,如JUser等。创建自定义脚本,使用来自API请求的值并使用Joomla用户类中的方法将用户保存在数据库中。

两种使用自定义代码添加Joomla用户的方法 是一篇非常好的教程,这种方法是可行的。我在一些项目中也使用了这种方法。

如果你需要在Joomla之外访问Joomla框架,请查看这个资源


4
损坏的链接。这就是为什么你应该始终在此处发布代码的原因... :( - MazarD

15

基于waitinforatrain的答案,该答案对于已登录用户不起作用(如果您在后端使用它实际上是危险的),我稍微进行了修改,现在完全适用于我。请注意,这是针对Joomla 2.5.6的,而此帖子最初是针对1.5的,因此以上答案可能不适用:

function addJoomlaUser($name, $username, $password, $email) {
    jimport('joomla.user.helper');

    $data = array(
        "name"=>$name,
        "username"=>$username,
        "password"=>$password,
        "password2"=>$password,
        "email"=>$email,
        "block"=>0,
        "groups"=>array("1","2")
    );

    $user = new JUser;
    //Write to database
    if(!$user->bind($data)) {
        throw new Exception("Could not bind data. Error: " . $user->getError());
    }
    if (!$user->save()) {
        throw new Exception("Could not save user. Error: " . $user->getError());
    }

    return $user->id;
 }

1
谢谢您发布这篇文章,我真的很需要看到最好的加密密码存储方式...但是懒得查看Joomla核心代码... - Cleanshooter
1
Themi,我认为我不能用希腊语回复,因为网站规则,并考虑到这些评论应该帮助其他读者的事实。尽管如此,我相信你面临的问题与联系组件表有关,可能与别名有关。你有搜索过吗?也许你可以在我的网站上联系我,这样我们可以更好地交流。(它与我的用户名完全相同,加上一个.com) - mavrosxristoforos
@mavrosxristoforos,您能否解释一下函数中“$cpassword”被用在哪里? - Mohd Abdul Mujib
1
@wardha-Web 我会说它在某个秘密函数中使用,但我无法说服任何人! :) 看起来那部分在那里并不是必要的,所以我把它改回了数据数组中的 $password。我可以确认它按照现在的方式工作,但如果你删除第3到5行,它也可能会工作。好点子,谢谢! - mavrosxristoforos
感谢 @mavrosxristoforos ,您的帖子对我在Joomla 3.0上有所帮助。然而,为了正常登录管理页面,需要进行修改。新用户应该是第7个管理员组的成员: "groups"=>array("1","2","7") - Yurii S
显示剩余2条评论

7

请前往文档页面查看:http://docs.joomla.org/JUser

此外,这是一个在Joomla中注册新用户的单页示例:

<?php 

function register_user ($email, $password){ 

 $firstname = $email; // generate $firstname
 $lastname = ''; // generate $lastname
 $username = $email; // username is the same as email


 /*
 I handle this code as if it is a snippet of a method or function!!

 First set up some variables/objects     */

 // get the ACL
 $acl =& JFactory::getACL();

 /* get the com_user params */

 jimport('joomla.application.component.helper'); // include libraries/application/component/helper.php
 $usersParams = &JComponentHelper::getParams( 'com_users' ); // load the Params

 // "generate" a new JUser Object
 $user = JFactory::getUser(0); // it's important to set the "0" otherwise your admin user information will be loaded

 $data = array(); // array for all user settings

 // get the default usertype
 $usertype = $usersParams->get( 'new_usertype' );
 if (!$usertype) {
     $usertype = 'Registered';
 }

 // set up the "main" user information

 //original logic of name creation
 //$data['name'] = $firstname.' '.$lastname; // add first- and lastname
 $data['name'] = $firstname.$lastname; // add first- and lastname

 $data['username'] = $username; // add username
 $data['email'] = $email; // add email
 $data['gid'] = $acl->get_group_id( '', $usertype, 'ARO' );  // generate the gid from the usertype

 /* no need to add the usertype, it will be generated automaticaly from the gid */

 $data['password'] = $password; // set the password
 $data['password2'] = $password; // confirm the password
 $data['sendEmail'] = 1; // should the user receive system mails?

 /* Now we can decide, if the user will need an activation */

 $useractivation = $usersParams->get( 'useractivation' ); // in this example, we load the config-setting
 if ($useractivation == 1) { // yeah we want an activation

     jimport('joomla.user.helper'); // include libraries/user/helper.php
     $data['block'] = 1; // block the User
     $data['activation'] =JUtility::getHash( JUserHelper::genRandomPassword() ); // set activation hash (don't forget to send an activation email)

 }
 else { // no we need no activation

     $data['block'] = 1; // don't block the user

 }

 if (!$user->bind($data)) { // now bind the data to the JUser Object, if it not works....

     JError::raiseWarning('', JText::_( $user->getError())); // ...raise an Warning
     return false; // if you're in a method/function return false

 }

 if (!$user->save()) { // if the user is NOT saved...

     JError::raiseWarning('', JText::_( $user->getError())); // ...raise an Warning
     return false; // if you're in a method/function return false

 }

 return $user; // else return the new JUser object

 }

 $email = JRequest::getVar('email');
 $password = JRequest::getVar('password');

 //echo 'User registration...'.'<br/>';
 register_user($email, $password);
 //echo '<br/>'.'User registration is completed'.'<br/>';
?>

请注意,注册时只需使用电子邮件和密码。
调用示例: localhost/joomla/test-reg-user-php?email=test02@test.com&password=pass 或者创建带有适当参数的简单表单。

1
$data['block'] = 1; // 不要阻止用户,应该是 $data['block'] = 0; - Dharmang
@molo 现在已经很晚了,我来评论一下还来得及吗?这个会发送 Joomla 核心激活邮件吗?同时,它是否会像之前一样遵守 Joomla 用户插件钩子的规则,在保存前或保存后执行? - Malaiselvan
代码怎么能够工作?你没有包含核心功能。 - nikksan

2

我已经发起了一个ajax调用,然后将变量传递给这个脚本,这对我有用。

define('_JEXEC', 1);
define('JPATH_BASE', __DIR__);
define('DS', DIRECTORY_SEPARATOR);

/* Required Files */
require_once(JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once(JPATH_BASE . DS . 'includes' . DS . 'framework.php');
$app = JFactory::getApplication('site');
$app->initialise();

require_once(JPATH_BASE . DS . 'components' . DS . 'com_users' . DS . 'models' . DS . 'registration.php');

$model = new UsersModelRegistration();

jimport('joomla.mail.helper');
jimport('joomla.user.helper');
$language = JFactory::getLanguage();
$language->load('com_users', JPATH_SITE);
$type       = 0;
$username   = JRequest::getVar('username');
$password   = JRequest::getVar('password');
$name       = JRequest::getVar('name');
$mobile     = JRequest::getVar('mobile');
$email      = JRequest::getVar('email');
$alias      = strtr($name, array(' ' => '-'));
$sendEmail  = 1;
$activation = 0;

$data       = array('username'   => $username,
            'name'       => $name,
            'email1'     => $email,
            'password1'  => $password, // First password field
            'password2'  => $password, // Confirm password field
            'sendEmail'  => $sendEmail,
            'activation' => $activation,
            'block'      => "0", 
            'mobile'     => $mobile,
            'groups'     => array("2", "10"));
$response   = $model->register($data);

echo $data['name'] . " saved!";
$model->register($data);

仅有用户不能自动激活。 我传递了'block' => "0"来激活用户,但它没有起作用 :( 但代码的其余部分运行良好。


2

已在2.5版本上进行过测试并可正常工作。

function addJoomlaUser($name, $username, $password, $email) {
        $data = array(
            "name"=>$name, 
            "username"=>$username, 
            "password"=>$password,
            "password2"=>$password,
            "email"=>$email
        );

        $user = clone(JFactory::getUser());
        //Write to database
        if(!$user->bind($data)) {
            throw new Exception("Could not bind data. Error: " . $user->getError());
        }
        if (!$user->save()) {
            throw new Exception("Could not save user. Error: " . $user->getError());
        }

        return $user->id;
}

如果您不在Joomla环境中,您需要先执行此操作;如果您不是编写组件,则可以使用@GMonC答案中链接中的组件。
<?php
if (! defined('_JEXEC'))
    define('_JEXEC', 1);
$DS=DIRECTORY_SEPARATOR;
define('DS', $DS);

//Get component path
preg_match("/\\{$DS}components\\{$DS}com_.*?\\{$DS}/", __FILE__, $matches, PREG_OFFSET_CAPTURE);
$component_path = substr(__FILE__, 0, strlen($matches[0][0]) + $matches[0][1]);
define('JPATH_COMPONENT', $component_path);

define('JPATH_BASE', substr(__FILE__, 0, strpos(__FILE__, DS.'components'.DS) ));
require_once ( JPATH_BASE .DS.'includes'.DS.'defines.php' );
require_once JPATH_BASE .DS.'includes'.DS.'framework.php';
jimport( 'joomla.environment.request' );
$mainframe =& JFactory::getApplication('site');
$mainframe->initialise();

我用这个来对我的组件进行单元测试。

谢谢,这对我很有帮助。一个问题:为什么要使用 $user = clone(JFactory::getUser()); 而不是 $user = new JUser(); - Tom
@Tom 我不记得为什么要那样做了。new JUser(); 可以用吗?如果可以的话,那会是一个更好的解决方案。 - bcoughlan

2

http://joomlaportal.ru/content/view/1381/68/

INSERT INTO jos_users( `name`, `username`, `password`, `email`, `usertype`, `gid` )
VALUES( 'Иванов Иван', 'ivanov', md5('12345'), 'ivanov@mail.ru', 'Registered', 18 );

INSERT INTO jos_core_acl_aro( `section_value`, `value` )
VALUES ( 'users', LAST_INSERT_ID() );

INSERT INTO jos_core_acl_groups_aro_map( `group_id`, `aro_id` )
VALUES ( 18, LAST_INSERT_ID() );

2

另一种聪明的方法是使用实际的/component/com_users/models/registration.php类方法,称为register,因为它将真正地处理所有事情。

首先,您需要将这些方法添加到您的辅助类中。

/**
*   Get any component's model
**/
public static function getModel($name, $path = JPATH_COMPONENT_ADMINISTRATOR, $component = 'yourcomponentname')
{
    // load some joomla helpers
    JLoader::import('joomla.application.component.model'); 
    // load the model file
    JLoader::import( $name, $path . '/models' );
    // return instance
    return JModelLegacy::getInstance( $name, $component.'Model' );
}   

/**
*   Random Key
*
*   @returns a string
**/
public static function randomkey($size)
{
    $bag = "abcefghijknopqrstuwxyzABCDDEFGHIJKLLMMNOPQRSTUVVWXYZabcddefghijkllmmnopqrstuvvwxyzABCEFGHIJKNOPQRSTUWXYZ";
    $key = array();
    $bagsize = strlen($bag) - 1;
    for ($i = 0; $i < $size; $i++)
    {
        $get = rand(0, $bagsize);
        $key[] = $bag[$get];
    }
    return implode($key);
}  

然后,您还需要在组件助手类中添加以下用户创建方法。
/**
* Greate user and update given table
*/
public static function createUser($new)
{
    // load the user component language files if there is an error
    $lang = JFactory::getLanguage();
    $extension = 'com_users';
    $base_dir = JPATH_SITE;
    $language_tag = 'en-GB';
    $reload = true;
    $lang->load($extension, $base_dir, $language_tag, $reload);
    // load the user regestration model
    $model = self::getModel('registration', JPATH_ROOT. '/components/com_users', 'Users');
    // set password
    $password = self::randomkey(8);
    // linup new user data
    $data = array(
        'username' => $new['username'],
        'name' => $new['name'],
        'email1' => $new['email'],
        'password1' => $password, // First password field
        'password2' => $password, // Confirm password field
        'block' => 0 );
    // register the new user
    $userId = $model->register($data);
    // if user is created
    if ($userId > 0)
    {
        return $userId;
    }
    return $model->getError();
}

然后在您的组件中任何地方,您可以像这样创建一个用户
// setup new user array
$newUser = array(
    'username' => $validData['username'], 
    'name' => $validData['name'], 
    'email' => $validData['email']
    );
$userId = yourcomponentnameHelper::createUser($newUser); 
if (!is_int($userId))
{
    $this->setMessage($userId, 'error');
}

通过这种方式做可以避免处理需要发送的邮件所带来的所有麻烦,因为它会自动使用系统默认值。希望这对某些人有所帮助 :)


1
更新:哦,我没有看到你想要1.5版本,但你可以使用类似的方法,只需使用1.5 API即可。
这是我用于其他目的的一部分,但在修复从命令行使用JUserHelper的问题之前,您需要使用默认组,或者将其制作为Web应用程序。
<?php
/**
 *
 * @copyright  Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

if (!defined('_JEXEC'))
{
    // Initialize Joomla framework
    define('_JEXEC', 1);
}

@ini_set('zend.ze1_compatibility_mode', '0');
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Load system defines
if (file_exists(dirname(__DIR__) . '/defines.php'))
{
    require_once dirname(__DIR__) . '/defines.php';
}

if (!defined('JPATH_BASE'))
{
    define('JPATH_BASE', dirname(__DIR__));
}

if (!defined('_JDEFINES'))
{
    require_once JPATH_BASE . '/includes/defines.php';
}

// Get the framework.
require_once JPATH_LIBRARIES . '/import.php';


/**
 * Add user
 *
 * @package  Joomla.Shell
 *
 * @since    1.0
 */
class Adduser extends JApplicationCli
{
    /**
     * Entry point for the script
     *
     * @return  void
     *
     * @since   1.0
     */
    public function doExecute()
    {
        // username, name, email, groups are required values.
        // password is optional
        // Groups is the array of groups

        // Long args
        $username = $this->input->get('username', null,'STRING');
        $name = $this->input->get('name');
        $email = $this->input->get('email', '', 'EMAIL');
        $groups = $this->input->get('groups', null, 'STRING');

        // Short args
        if (!$username)
        {
            $username = $this->input->get('u', null, 'STRING');
        }
        if (!$name)
        {
            $name = $this->input->get('n');
        }
        if (!$email)
        {
            $email = $this->input->get('e', null, 'EMAIL');
        }
        if (!$groups)
        {
            $groups = $this->input->get('g', null, 'STRING');
        }

        $user = new JUser();

        $array = array();
        $array['username'] = $username;
        $array['name'] = $name;
        $array['email'] = $email;

        $user->bind($array);
        $user->save();

        $grouparray = explode(',', $groups);
        JUserHelper::setUserGroups($user->id, $grouparray);
        foreach ($grouparray as $groupId)
        {
            JUserHelper::addUserToGroup($user->id, $groupId);
        }

        $this->out('User Created');

        $this->out();
    }

}

if (!defined('JSHELL'))
{
    JApplicationCli::getInstance('Adduser')->execute();
}

谢谢,这对2.5版本很有帮助。群组代码对我不起作用,但我会继续尝试,我认为这是因为我的群组名称中有空格“Foo Bar”。我会继续尝试。如果您有其他见解,那将非常有帮助。 - Tom
哦,你知道吗,我忘记了我有一个拉取请求来修复创建组时的错误。 - Elin
那个拉取请求最近已经合并,将会在3.1版本中发布。 - Elin
@Elin 我需要从csv文件中导入一堆用户,并希望在此处使用你的代码。但当我在Joomla 3.3.6中尝试时,我收到了错误提示,如“显示错误页面错误:应用程序实例化错误:访问用户组无效”。如果您能更新您的代码以与Joomla3.3.x一起使用,我会非常感激的。谢谢Elin。 - Danniel Little
你确定你要发送的用户组存在吗?你能运行其他CLI应用程序吗?(尝试在cli文件夹中进行垃圾收集)。我谷歌了一下你的错误信息,看起来好像是如果安装了第三方用户插件就会发生这种情况。你能检查一下吗?如果是这样,你可以暂时禁用它,或者修改我的代码以在CLI中禁用它。 - Elin

1
在我的情况下(Joomla 3.4.3),用户已被添加到会话中,因此在尝试激活帐户时出现了错误行为。只需在 $user->save() 后添加此行代码: JFactory::getSession()->clear('user', "default"); 这将从会话中移除新创建的用户。

0

有一个名为“登录模块”的模块,您可以使用该模块并将其显示在菜单中的其中一个位置。 在其中,您将获得一个链接,例如“新用户?”或“创建帐户”,只需单击即可获得一个带有验证的注册页面。这只是使用注册页面的三个步骤...它可能有助于更快地获得结果!..谢谢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接