包 | system.web.auth |
---|---|
继承 | class CDbAuthManager » CAuthManager » CApplicationComponent » CComponent |
实现 | IAuthManager, IApplicationComponent |
源自 | 1.0 |
版本 | $Id: CDbAuthManager.php 3515 2011-12-28 12:29:24Z mdomba $ |
源码 |
CDbAuthManager代表一种在数据库里存储授权信息的授权管理器。
数据库连接是由connectionID指定的。数据库架构应该描述为 “framework/web/auth/*.sql”。你可以通过设置itemTable,itemChildTable和 assignmentTable来修改 这三个用来存储验证数据的数据表。
数据库连接是由connectionID指定的。数据库架构应该描述为 “framework/web/auth/*.sql”。你可以通过设置itemTable,itemChildTable和 assignmentTable来修改 这三个用来存储验证数据的数据表。
公共属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
assignmentTable | string | 保存授权项目任务的数据表名字。默认为‘AuthAssignment’。 | CDbAuthManager |
authItems | array | 返回指定类型和用户的授权项目。 | CDbAuthManager |
behaviors | array | 这个应用组件附加的行为。 这此行为将在应用组件调用init时附加在应用组件上。 请参照CModel::behaviors如何指定此属性值。 | CApplicationComponent |
connectionID | string | CDbConnection应用组件的ID。默认为‘db’。 数据库里面必须包含着在"framework/web/auth/*. | CDbAuthManager |
db | CDbConnection | 数据库连接对象。默认是,这个会根据应用组件里面公认的connectionIDID自动 初始化的。 | CDbAuthManager |
defaultRoles | array | 隐式赋予给所有用户的角色名字列表。 这些角色不需要显式赋予给所有用户。 当调用checkAccess,会首先检查这些角色。 为了能够提高程序效率,这样的角色越少越好。 一个典型的用法是,定义一个“authenticated”角色,然后 把它关联到一个业务逻辑规则,这个规则是用来验证当前用户的。 然后在这个属性声明“authenticated”以便应用到 所有的验证用户。 | CAuthManager |
isInitialized | boolean | 检查应用组件是否已经初始化。 | CApplicationComponent |
itemChildTable | string | 保存授权项目层级关系的数据表名字。默认为‘AuthItemChild’。 | CDbAuthManager |
itemTable | string | 保存授权项目的数据表名字。默认为‘AuthItem’。 | CDbAuthManager |
operations | array | 返回操作。 | CAuthManager |
roles | array | 返回角色。 | CAuthManager |
showErrors | boolean | 允许业务规则错误报告。 | CAuthManager |
tasks | array | 返回任务。 | CAuthManager |
受保护属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
dbConnection | CDbConnection | 数据库连接对象。 | CDbAuthManager |
公共方法
受保护方法
方法 | 描述 | 定义在 |
---|---|---|
checkAccessRecursive() | 检测指定用户的访问权限。 | CDbAuthManager |
checkItemChildType() | 检查项目类型以确定一个子项目已经赋予给一个父项目。 | CAuthManager |
detectLoop() | 检测是否在授权项目层级中存在循环。 | CDbAuthManager |
getDbConnection() | 返回数据库连接对象。 | CDbAuthManager |
usingSqlite() | CDbAuthManager |
属性详细
assignmentTable
属性
public string $assignmentTable;
保存授权项目任务的数据表名字。默认为‘AuthAssignment’。
authItems
属性
只读
public array getAuthItems(integer $type=NULL, mixed $userId=NULL)
返回指定类型和用户的授权项目。
connectionID
属性
public string $connectionID;
CDbConnection应用组件的ID。默认为‘db’。 数据库里面必须包含着在"framework/web/auth/*.sql"声明的数据表。
db
属性
public CDbConnection $db;
数据库连接对象。默认是,这个会根据应用组件里面公认的connectionIDID自动 初始化的。
dbConnection
属性
只读
protected CDbConnection getDbConnection()
数据库连接对象。
itemChildTable
属性
public string $itemChildTable;
保存授权项目层级关系的数据表名字。默认为‘AuthItemChild’。
itemTable
属性
public string $itemTable;
保存授权项目的数据表名字。默认为‘AuthItem’。
方法详细
addItemChild()
方法
public boolean addItemChild(string $itemName, string $childName)
| ||
$itemName | string | 父项目名字 |
$childName | string | 子项目名字 |
{return} | boolean | 添加是否成功。 |
public function addItemChild($itemName,$childName)
{
if($itemName===$childName)
throw new CException(Yii::t('yii','Cannot add "{name}" as a child of itself.',
array('{name}'=>$itemName)));
$rows=$this->db->createCommand()
->select()
->from($this->itemTable)
->where('name=:name1 OR name=:name2', array(
':name1'=>$itemName,
':name2'=>$childName
))
->queryAll();
if(count($rows)==2)
{
if($rows[0]['name']===$itemName)
{
$parentType=$rows[0]['type'];
$childType=$rows[1]['type'];
}
else
{
$childType=$rows[0]['type'];
$parentType=$rows[1]['type'];
}
$this->checkItemChildType($parentType,$childType);
if($this->detectLoop($itemName,$childName))
throw new CException(Yii::t('yii','Cannot add "{child}" as a child of "{name}". A loop has been detected.',
array('{child}'=>$childName,'{name}'=>$itemName)));
$this->db->createCommand()
->insert($this->itemChildTable, array(
'parent'=>$itemName,
'child'=>$childName,
));
return true;
}
else
throw new CException(Yii::t('yii','Either "{parent}" or "{child}" does not exist.',array('{child}'=>$childName,'{parent}'=>$itemName)));
}
将一个项目作为一个子项目添加。
assign()
方法
public CAuthAssignment assign(string $itemName, mixed $userId, string $bizRule=NULL, mixed $data=NULL)
| ||
$itemName | string | 项目名字 |
$userId | mixed | 用户ID(详情请参考IWebUser::getId)。 |
$bizRule | string | 当调用checkAccess时, 具体的授权项目的业务规则。 |
$data | mixed | 这个任务额外的数据。 |
{return} | CAuthAssignment | 授权任务的信息。 |
public function assign($itemName,$userId,$bizRule=null,$data=null)
{
if($this->usingSqlite() && $this->getAuthItem($itemName)===null)
throw new CException(Yii::t('yii','The item "{name}" does not exist.',array('{name}'=>$itemName)));
$this->db->createCommand()
->insert($this->assignmentTable, array(
'itemname'=>$itemName,
'userid'=>$userId,
'bizrule'=>$bizRule,
'data'=>serialize($data)
));
return new CAuthAssignment($this,$itemName,$userId,$bizRule,$data);
}
将授权项目赋予给用户。
checkAccess()
方法
public void checkAccess(string $itemName, mixed $userId, array $params=array (
))
| ||
$itemName | string | 需要检测的访问操作名字 |
$userId | mixed | 用户ID。这个可以是数字,或者是唯一识别用户身份的 字符串。详情请看IWebUser::getId。 |
$params | array | 键名-键值对,将关联到用户的任务和角色传递给 业务规则。 |
public function checkAccess($itemName,$userId,$params=array())
{
$assignments=$this->getAuthAssignments($userId);
return $this->checkAccessRecursive($itemName,$userId,$params,$assignments);
}
检测指定用户的访问权限。
checkAccessRecursive()
方法
(可用自 v1.1.3)
protected boolean checkAccessRecursive(string $itemName, mixed $userId, array $params, array $assignments)
| ||
$itemName | string | 需要检测的访问操作名字 |
$userId | mixed | 用户ID。这个可以是数字,或者是唯一识别用户身份的 字符串。详情请看IWebUser::getId。 |
$params | array | 键名-键值对,将关联到用户的任务和角色传递给 业务规则。 |
$assignments | array | 指定用户的任务 |
{return} | boolean | 返回值说明用户是否有权限进行操作。 |
protected function checkAccessRecursive($itemName,$userId,$params,$assignments)
{
if(($item=$this->getAuthItem($itemName))===null)
return false;
Yii::trace('Checking permission "'.$item->getName().'"','system.web.auth.CDbAuthManager');
if($this->executeBizRule($item->getBizRule(),$params,$item->getData()))
{
if(in_array($itemName,$this->defaultRoles))
return true;
if(isset($assignments[$itemName]))
{
$assignment=$assignments[$itemName];
if($this->executeBizRule($assignment->getBizRule(),$params,$assignment->getData()))
return true;
}
$parents=$this->db->createCommand()
->select('parent')
->from($this->itemChildTable)
->where('child=:name', array(':name'=>$itemName))
->queryColumn();
foreach($parents as $parent)
{
if($this->checkAccessRecursive($parent,$userId,$params,$assignments))
return true;
}
}
return false;
}
检测指定用户的访问权限。 这个方法是checkAccess内部调用。
clearAll()
方法
public void clearAll()
|
public function clearAll()
{
$this->clearAuthAssignments();
$this->db->createCommand()->delete($this->itemChildTable);
$this->db->createCommand()->delete($this->itemTable);
}
移除所有授权数据。
clearAuthAssignments()
方法
public void clearAuthAssignments()
|
public function clearAuthAssignments()
{
$this->db->createCommand()->delete($this->assignmentTable);
}
移除所有授权任务。
createAuthItem()
方法
public CAuthItem createAuthItem(string $name, integer $type, string $description='', string $bizRule=NULL, mixed $data=NULL)
| ||
$name | string | 项目名字。这个一个是唯一标识。 |
$type | integer | 项目类型(0:操作,1:任务,2:角色)。 |
$description | string | 项目描述 |
$bizRule | string | 关联到项目的业务规则。这里是PHP代码段,当调用checkAccess时 会执行。 |
$data | mixed | 项目关联的额外数据。 |
{return} | CAuthItem | 授权项目 |
public function createAuthItem($name,$type,$description='',$bizRule=null,$data=null)
{
$this->db->createCommand()
->insert($this->itemTable, array(
'name'=>$name,
'type'=>$type,
'description'=>$description,
'bizrule'=>$bizRule,
'data'=>serialize($data)
));
return new CAuthItem($this,$name,$type,$description,$bizRule,$data);
}
创建一个授权项目。 代表动作权限的授权项目(如,创建一个内容)。 它有三种类型:操作,任务,角色。 层级授权项目。高层项目继承 低层项目的权限。
detectLoop()
方法
protected boolean detectLoop(string $itemName, string $childName)
| ||
$itemName | string | 父项目名字 |
$childName | string | 添加到层级的子项目名字。 |
{return} | boolean | 返回值说明是否存在循环 |
protected function detectLoop($itemName,$childName)
{
if($childName===$itemName)
return true;
foreach($this->getItemChildren($childName) as $child)
{
if($this->detectLoop($itemName,$child->getName()))
return true;
}
return false;
}
检测是否在授权项目层级中存在循环。
getAuthAssignment()
方法
public CAuthAssignment getAuthAssignment(string $itemName, mixed $userId)
| ||
$itemName | string | 项目名字 |
$userId | mixed | 用户ID(详情请参考IWebUser::getId)。 |
{return} | CAuthAssignment | 项目任务信息。如果没有赋予给用户, 则返回null。 |
public function getAuthAssignment($itemName,$userId)
{
$row=$this->db->createCommand()
->select()
->from($this->assignmentTable)
->where('itemname=:itemname AND userid=:userid', array(
':itemname'=>$itemName,
':userid'=>$userId))
->queryRow();
if($row!==false)
{
if(($data=@unserialize($row['data']))===false)
$data=null;
return new CAuthAssignment($this,$row['itemname'],$row['userid'],$row['bizrule'],$data);
}
else
return null;
}
返回项目任务信息。
getAuthAssignments()
方法
public array getAuthAssignments(mixed $userId)
| ||
$userId | mixed | 用户ID(详情请参考IWebUser::getId)。 |
{return} | array | 用户的项目任务信息。如果没有项目赋予给用户, 则返回null。 |
public function getAuthAssignments($userId)
{
$rows=$this->db->createCommand()
->select()
->from($this->assignmentTable)
->where('userid=:userid', array(':userid'=>$userId))
->queryAll();
$assignments=array();
foreach($rows as $row)
{
if(($data=@unserialize($row['data']))===false)
$data=null;
$assignments[$row['itemname']]=new CAuthAssignment($this,$row['itemname'],$row['userid'],$row['bizrule'],$data);
}
return $assignments;
}
返回指定用户的项目任务。
getAuthItem()
方法
public CAuthItem getAuthItem(string $name)
| ||
$name | string | 项目名字 |
{return} | CAuthItem | 授权项目。如果找不到该项目,则返回null。 |
public function getAuthItem($name)
{
$row=$this->db->createCommand()
->select()
->from($this->itemTable)
->where('name=:name', array(':name'=>$name))
->queryRow();
if($row!==false)
{
if(($data=@unserialize($row['data']))===false)
$data=null;
return new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
}
else
return null;
}
返回指定名字的授权项目。
getAuthItems()
方法
public array getAuthItems(integer $type=NULL, mixed $userId=NULL)
| ||
$type | integer | 项目类型(0:操作,1:任务,2:角色)。默认为null, 意味着返回所有类型。 |
$userId | mixed | 用户ID。默认为null,意味着即使没有赋予给用户, 也返回所有的项目。 |
{return} | array | 指定类型的授权项目。 |
public function getAuthItems($type=null,$userId=null)
{
if($type===null && $userId===null)
{
$command=$this->db->createCommand()
->select()
->from($this->itemTable);
}
else if($userId===null)
{
$command=$this->db->createCommand()
->select()
->from($this->itemTable)
->where('type=:type', array(':type'=>$type));
}
else if($type===null)
{
$command=$this->db->createCommand()
->select('name,type,description,t1.bizrule,t1.data')
->from(array(
$this->itemTable.' t1',
$this->assignmentTable.' t2'
))
->where('name=itemname AND userid=:userid', array(':userid'=>$userId));
}
else
{
$command=$this->db->createCommand()
->select('name,type,description,t1.bizrule,t1.data')
->from(array(
$this->itemTable.' t1',
$this->assignmentTable.' t2'
))
->where('name=itemname AND type=:type AND userid=:userid', array(
':type'=>$type,
':userid'=>$userId
));
}
$items=array();
foreach($command->queryAll() as $row)
{
if(($data=@unserialize($row['data']))===false)
$data=null;
$items[$row['name']]=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
}
return $items;
}
返回指定类型和用户的授权项目。
getDbConnection()
方法
protected CDbConnection getDbConnection()
| ||
{return} | CDbConnection | 数据库连接对象。 |
protected function getDbConnection()
{
if($this->db!==null)
return $this->db;
else if(($this->db=Yii::app()->getComponent($this->connectionID)) instanceof CDbConnection)
return $this->db;
else
throw new CException(Yii::t('yii','CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.',
array('{id}'=>$this->connectionID)));
}
getItemChildren()
方法
public array getItemChildren(mixed $names)
| ||
$names | mixed | 父项目名字。可以是字符串或数组。 后者代表项目名字列表。 |
{return} | array | 父项目的所有子项目。 |
public function getItemChildren($names)
{
if(is_string($names))
$condition='parent='.$this->db->quoteValue($names);
else if(is_array($names) && $names!==array())
{
foreach($names as &$name)
$name=$this->db->quoteValue($name);
$condition='parent IN ('.implode(', ',$names).')';
}
$rows=$this->db->createCommand()
->select('name, type, description, bizrule, data')
->from(array(
$this->itemTable,
$this->itemChildTable
))
->where($condition.' AND name=child')
->queryAll();
$children=array();
foreach($rows as $row)
{
if(($data=@unserialize($row['data']))===false)
$data=null;
$children[$row['name']]=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
}
return $children;
}
返回这个项目的所有子项目。
hasItemChild()
方法
public boolean hasItemChild(string $itemName, string $childName)
| ||
$itemName | string | 父项目名字 |
$childName | string | 子项目名字 |
{return} | boolean | 子项目是否存在 |
public function hasItemChild($itemName,$childName)
{
return $this->db->createCommand()
->select('parent')
->from($this->itemChildTable)
->where('parent=:parent AND child=:child', array(
':parent'=>$itemName,
':child'=>$childName))
->queryScalar() !== false;
}
返回一个值说明这个子项目是否存在
init()
方法
public void init()
|
public function init()
{
parent::init();
$this->_usingSqlite=!strncmp($this->getDbConnection()->getDriverName(),'sqlite',6);
}
初始化这个应用组件。 这个方法覆盖父类方法,实现了数据库连接。
isAssigned()
方法
public boolean isAssigned(string $itemName, mixed $userId)
| ||
$itemName | string | 项目名字 |
$userId | mixed | 用户ID(详情请参考IWebUser::getId)。 |
{return} | boolean | 这个项目是否已经赋予给用户。 |
public function isAssigned($itemName,$userId)
{
return $this->db->createCommand()
->select('itemname')
->from($this->assignmentTable)
->where('itemname=:itemname AND userid=:userid', array(
':itemname'=>$itemName,
':userid'=>$userId))
->queryScalar() !== false;
}
返回值说明这个项目是否已经赋予给用户。
removeAuthItem()
方法
public boolean removeAuthItem(string $name)
| ||
$name | string | 要移除的项目名字 |
{return} | boolean | 存储器存在的项目是否已经移除成功。 |
public function removeAuthItem($name)
{
if($this->usingSqlite())
{
$this->db->createCommand()
->delete($this->itemChildTable, 'parent=:name1 OR child=:name2', array(
':name1'=>$name,
':name2'=>$name
));
$this->db->createCommand()
->delete($this->assignmentTable, 'itemname=:name', array(
':name'=>$name,
));
}
return $this->db->createCommand()
->delete($this->itemTable, 'name=:name', array(
':name'=>$name
)) > 0;
}
移除指定的授权项目。
removeItemChild()
方法
public boolean removeItemChild(string $itemName, string $childName)
| ||
$itemName | string | 父项目名字 |
$childName | string | 子项目名字 |
{return} | boolean | 移除是否成功 |
public function removeItemChild($itemName,$childName)
{
return $this->db->createCommand()
->delete($this->itemChildTable, 'parent=:parent AND child=:child', array(
':parent'=>$itemName,
':child'=>$childName
)) > 0;
}
移除子项目。 要注意的是,子项目是没有被删除的。只是它跟父项目的关系解。
revoke()
方法
public boolean revoke(string $itemName, mixed $userId)
| ||
$itemName | string | 项目名字 |
$userId | mixed | 用户ID(详情请参考IWebUser::getId)。 |
{return} | boolean | 撤消是否成功 |
public function revoke($itemName,$userId)
{
return $this->db->createCommand()
->delete($this->assignmentTable, 'itemname=:itemname AND userid=:userid', array(
':itemname'=>$itemName,
':userid'=>$userId
)) > 0;
}
撤消用户的授权任务。
save()
方法
public void save()
|
public function save()
{
}
将授权数据保存到持久化存储器。
saveAuthAssignment()
方法
public void saveAuthAssignment(CAuthAssignment $assignment)
| ||
$assignment | CAuthAssignment | 已经修改过的任务。 |
public function saveAuthAssignment($assignment)
{
$this->db->createCommand()
->update($this->assignmentTable, array(
'bizrule'=>$assignment->getBizRule(),
'data'=>serialize($assignment->getData()),
), 'itemname=:itemname AND userid=:userid', array(
'itemname'=>$assignment->getItemName(),
'userid'=>$assignment->getUserId()
));
}
保存修改过的授权任务。
saveAuthItem()
方法
public void saveAuthItem(CAuthItem $item, string $oldName=NULL)
| ||
$item | CAuthItem | 要保存的项目。 |
$oldName | string | 旧的项目名字。如果为null,意味着项目名字没有改变。 |
public function saveAuthItem($item,$oldName=null)
{
if($this->usingSqlite() && $oldName!==null && $item->getName()!==$oldName)
{
$this->db->createCommand()
->update($this->itemChildTable, array(
'parent'=>$item->getName(),
), 'parent=:whereName', array(
':whereName'=>$oldName,
));
$this->db->createCommand()
->update($this->itemChildTable, array(
'child'=>$item->getName(),
), 'child=:whereName', array(
':whereName'=>$oldName,
));
$this->db->createCommand()
->update($this->assignmentTable, array(
'itemname'=>$item->getName(),
), 'itemname=:whereName', array(
':whereName'=>$oldName,
));
}
$this->db->createCommand()
->update($this->itemTable, array(
'name'=>$item->getName(),
'type'=>$item->getType(),
'description'=>$item->getDescription(),
'bizrule'=>$item->getBizRule(),
'data'=>serialize($item->getData()),
), 'name=:whereName', array(
':whereName'=>$oldName===null?$item->getName():$oldName,
));
}
将授权项目保存到持久化存储器。
usingSqlite()
方法
protected boolean usingSqlite()
| ||
{return} | boolean | 数据库是否是SQLite |
protected function usingSqlite()
{
return $this->_usingSqlite;
}