本文将会介绍如何将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;
}

评论 (0)