mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-09-04 07:01:37 +08:00
feat(mcp): 密钥授权页,仅创建者拥有的节点可授权(防越权与漂移)
This commit is contained in:
@@ -96,6 +96,33 @@ class AuthServiceBase
|
||||
return static::$dynamicNodeList[$node];
|
||||
}
|
||||
|
||||
// 判断是否需要获取当前节点
|
||||
if (empty($node)) {
|
||||
$node = $this->getCurrentNode();
|
||||
} else {
|
||||
$node = $this->parseNodeStr($node);
|
||||
}
|
||||
|
||||
return $this->checkNodeResolved($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对已规范化(parseNodeStr 后)的单个节点执行完整判定链.
|
||||
*
|
||||
* checkNode 与 getAdminAllowedNodes 共用此实现,严禁平行复制导致语义漂移。
|
||||
* 判定链(顺序与原 checkNode 保持一致):
|
||||
* 动态节点黑名单 → 超管直通 → auth_on 开关 → 未注册节点 default_auth_check
|
||||
* → 注解 auth=false → status/auth_ids 校验 → 白名单成员判定
|
||||
* @param string $node
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkNodeResolved($node)
|
||||
{
|
||||
// 动态节点开关(按规范化节点命中)
|
||||
if (isset(static::$dynamicNodeList[$node])) {
|
||||
return static::$dynamicNodeList[$node];
|
||||
}
|
||||
|
||||
// 判断是否为超级管理员
|
||||
if ($this->isSuperAdmin()) {
|
||||
return true;
|
||||
@@ -104,12 +131,6 @@ class AuthServiceBase
|
||||
if ($this->config['auth_on'] == false) {
|
||||
return true;
|
||||
}
|
||||
// 判断是否需要获取当前节点
|
||||
if (empty($node)) {
|
||||
$node = $this->getCurrentNode();
|
||||
} else {
|
||||
$node = $this->parseNodeStr($node);
|
||||
}
|
||||
|
||||
// 判断是否加入节点控制,优先获取缓存信息
|
||||
if (!isset($this->nodeList[$node])) {
|
||||
@@ -131,6 +152,35 @@ class AuthServiceBase
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取管理员对候选节点集合的允许子集.
|
||||
*
|
||||
* 对每个候选节点走与 checkNode() 完全一致的判定链(共用 checkNodeResolved),
|
||||
* 返回其中允许访问的节点(规范化后的形式,保持候选顺序并去重)。
|
||||
* 用于 MCP 密钥授权(创建者权限子集)等批量场景。
|
||||
* @param array $candidateNodes 候选节点列表(controller/action 形式,内部会做 parseNodeStr 规范化)
|
||||
* @param int|null $adminId 管理员ID,为 null 时沿用当前实例的管理员
|
||||
* @return array 允许的节点列表
|
||||
*/
|
||||
public function getAdminAllowedNodes(array $candidateNodes, ?int $adminId = null): array
|
||||
{
|
||||
if (empty($adminId)) {
|
||||
$adminId = $this->adminId;
|
||||
}
|
||||
// 目标管理员与当前实例不一致时,按目标管理员重建判定上下文
|
||||
$service = ($adminId == $this->adminId) ? $this : new static($adminId);
|
||||
|
||||
$allowedNodes = [];
|
||||
foreach ($candidateNodes as $node) {
|
||||
$node = $service->parseNodeStr($node);
|
||||
if ($service->checkNodeResolved($node) && !in_array($node, $allowedNodes)) {
|
||||
$allowedNodes[] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
return $allowedNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前节点.
|
||||
* @return string
|
||||
|
||||
Reference in New Issue
Block a user