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