本文将会介绍如何将ACL添加到你的组件,并且在你的组件的对象级别对他们的访问进行控制(我的理解是如何控制一条记录的访问权限)。一般情况下, 我们都是使用全局的ACL控制,或者分类级和组件级的ACL控制(这句话大概是说我们通常用ACL来控制哪些分类可以给哪些用户,哪些组件可以被哪些指定 的用户来访问)。那么现在我们要进行更细小的一部分了,如何控制我们组件中的一条记录的ACL.

ACL的结构

在j25X中,ACL有3个等级,分别是:

1,全局配置:这一层级主要是为每一个用户组定义默认的访问权限。

2,组件的选项->权限设置:这个主要是用我们自定的权限去覆盖全局的权限设置。

3,记录的选项->权限配置:在数据库的记录(对向级)上对权限的控制。

在上面我们并没有提到分类级,分类的权限控制会覆盖权限的权限设置,如果我们在自己的组件中使用了分类,我们就可以控制在该分类的项目的访问权限了。


修改自己的数据库表的结构

 为了进行记录级的控制,我们需要在我们的数据库表中增加一个字段asset-id(资源的标识符),如果你的数据表的结构中没有这个字段,那么就应该加上了。

ALTER TABLE '#__asterman_units' ADD 'asset_id'  INT(255) UNSIGNED NOT NULL DEFAULT '0' AFTER 'id'

 

利用JTable去处理ACL的保存和加载

JTable类支持ACL,为了使用JTable的ACL,我们需要增减一个int字段 asset_id.这个字段就将会记录你对这个记录的操作权限。这里需要区分‘access’字段,这个字段仅仅控制joomla对该操作是否可读。

通常我们需要在子类中重载构造函数:__construct()方法。我们也可以通过重载check()方法来校验数据。为了获得JTable类的ACL支持,我们需要重载下面的方法:

public function bind($array ,$ignore =) ,在这个里面我们让JTable储存ACL规则到joomla的assets表中。

protected function _getAssetName() 让JTable为我们的资源指定一个资源的名称

protected function _getAssetParentId($table = null ,$id = null)。在这里指定我们资源的parent ID.一般情况下,joomla用1表示parent.在这里我们需要将他修改为我们的组件。重载了上面的3个方法,JTable就会自动的帮我们完成资 源的加载和保存。


 JTable的一个例子

<?php
class AstermanTableUnit extends JTable
{
	public function __construct($db)
	{
		parent::__construct('#__asterman_units' ,'id' ,$db);
	}
	
	public function bind($array ,$ignore ='')
	{
		//Bind the rules
		if(isset($array['rules']) && is_array($array['rules']))
		{
			$rules = new JRules($array['rules']);
			$this->setRules($rules);
		}
		return parent::bind($array ,$ignore);
	}
	/**
	 *	Redefined asset name ,as we support action control
	 */
	 protected function _getAssetName()
	 {
		$k = $this->_tbl_key;
		return 'com_asterman.unit.'.(int)$this->k;
	 }
	 
	 /**
	  *	We provide our global ACL as parent
	  * @see JTable::_getAssetParentId()
	  */
	  protected function _getAssetParentId($table = null,$id = null)
	  {
		$asset = JTable::getInstance('Asset');
		$asset->loadByName('com_asterman');
		return $asset->id;
	  }
	
}

?>

 上面的代码就是简单的完成了4个函数的重载,其中每一个函数的具体意义,还需要以后仔细看看。


 向表单中增加规则字段

接 下来,为了能够让用户设置ACL,我们需要在表单中增加两个字段。第一个字段是'asset_id',他的类型是hidden.这个名字和我们在数据库表 中用到的名字要保持一致(??)。第二个字段是'rules',他的类型是‘rules’.我们必须提供这个名称,因为在JTable的子类中会用到这个 名称。(想了解更多,参考JTable类)

<fieldset name="accesscontrol">
	<field name="asset_id" type="hidden" filter="unset" />
	<field
		name="rules"
		type="rules"
		lable="JFIELD_RULES_LABEL"
		translate_label="false"
		filter="rules"
		validate="rules"
		class="inputbox"
		component="com_asterman"
		section="unit"
	/>
</fieldset>

 因为用到了rules字段类型,因此我们必须设置componet attribute为我们的组件的名称。section attribute为我们在access.xml定义的值。下面是一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<access component="com_asterman">
	<section name="component">
		<!--  Actions to be used in our global component-->
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC"/>
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC"/>
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC"/>
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC"/>
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC"/>
		<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC"/>
	</section>
	
	<section name="unit">
		<!-- Actions to be used in for unit -->
		<action name="core.create" title="JACTION_CREATE" description="COM_ASTERMAN_ACTION_CREATE_UNIT_DESC"/>
		<action name="core.delete" title="JACTION_DELETE" description="COM_ASTERMAN_ACTION_DELETE_UNIT_DESC"/>
		<action name="core.edit" title="JACTION_EDIT" description="COM_ASTERMAN_ACTION_EDIT_UNIT_DESC"/>
		<action name="asterman.edit.basic" title="COM_ASTERMAN_ACTION_EDITBASIC" description="COM_ASTERMAN_ACTION_EDITBASIC_DESC"/>
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_ASTERMAN_ACTION_EDITSTATE_UNIT_DESC"/>
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_ASTERMAN_ACTION_EDITOWN_UNIT_DESC"/>
	</section>
</access>

 上面的代码中增加了一个新的Action(asterman.edit.basic),这个用来控制是否一个用户有权利去编辑这个记录的一部分。


将ACL放到控制操作的代码中

在JUser类中,有一个authorise()方法,这个方法需要两个参数,一个是需要判断权限的行动名称,一个是资源的名称。不同于全局配置中的访问控制,我们需要设置每一条记录的资源名称。

JFactory::getUser()->authorise($action ,$asset name);

 下面是一个使用JModelAdmin的一个代码范例:

 

public function getForm($data = array(), $loadData = true)
{
    // Get the form.
    $form = $this->loadForm('com_asterman.extension', //form name
            'extension', //XML file name
            array(
                'control' => 'jform',
                'load_data' => $loadData
            ));
 
    if (empty($form)) {
        return false;
    }
 
    if ($this->getState('suffix') == '14') {
        // theses fields do not exists in Asterisk version 1.4
        $form->setFieldAttribute('call-limit', 'disabled', 'true');
        $form->setFieldAttribute('call-limit', 'filter', 'unset');
    }
 
    $user = JFactory::getUser();
 
    if (!empty($data['unit_id'])) {
        $assetName = $this->option . '.unit.' . $data['unit_id'];
 
        $canEdit = $user->authorise('core.edit', $assetName);
        $canEditBasic = $user->authorise('asterman.edit.basic', $assetName);
        $canEditState = $user->authorise('core.edit.state', $assetName);
    } else {
        $canEdit = $user->authorise('core.create', $this->option);
    }
 
    if (!$canEdit) {
 
        $form->setFieldAttribute('unit_id', 'disabled', 'true');
        $form->setFieldAttribute('unit_id', 'filter', 'unset');
 
        if (!$canEditBasic) {
            $form->setFieldAttribute('callerid', 'disabled', 'true');
            $form->setFieldAttribute('secret', 'disabled', 'true');
            $form->setFieldAttribute('allow', 'disabled', 'true');
            $form->setFieldAttribute('callgroup', 'disabled', 'true');
            $form->setFieldAttribute('pickupgroup', 'disabled', 'true');
            $form->setFieldAttribute('call-limit', 'disabled', 'true');
 
            $form->setFieldAttribute('callerid', 'filter', 'unset');
            $form->setFieldAttribute('secret', 'filter', 'unset');
            $form->setFieldAttribute('allow', 'filter', 'unset');
            $form->setFieldAttribute('callgroup', 'filter', 'unset');
            $form->setFieldAttribute('pickupgroup', 'filter', 'unset');
            $form->setFieldAttribute('call-limit', 'filter', 'unset');
        }
 
        // Modify the form based on access controls.
        if (!$canEditState) {
            // Disable fields for display.
            $form->setFieldAttribute('host', 'disabled', 'true');
            $form->setFieldAttribute('context', 'disabled', 'true');
 
            // Disable fields while saving.
            // The controller has already verified this is a record you can edit.
            $form->setFieldAttribute('host', 'filter', 'unset');
            $form->setFieldAttribute('context', 'filter', 'unset');
        }
    }
 
    return $form;
}

 

作者: 樱木花道

Joomla程序员,从J1.5到J4.x始终都在做Joomla相关开发定制工作,有超过10年行业经验,国内Joomla扩展开发商ZMAX团队的核心成员

作者网站:ZMAX程序人

评论 (0)

  • 最新在前
  • 最佳在前