Access Control

概述

Access Control 模块为 Soroban 合约提供了一个全面的基于角色的访问控制系统。它使开发者能够通过分层角色系统来管理权限,该系统具有可放弃的单一管理权限和可自定义的角色分配。

关键概念

管理员管理

该系统具有一个顶层管理员,该管理员有权调用 AccessControl trait 中的任何函数。必须在合约初始化期间设置此管理员,模块才能正常运行。为了实现去中心化,这个总管理员可以放弃自己的权限。

管理员转移实现为两步过程,以防止意外或恶意的接管:

  1. 当前管理员通过指定新管理员和过期时间 (live_until_ledger) *发起*转移。

  2. 指定的新管理员必须*显式接受*转移才能完成它。

在转移被接受之前,原始管理员保留完全控制权,并且可以通过发起新的转移或使用 live_until_ledger0 来覆盖或取消转移。

角色层次结构

该模块支持分层角色系统,其中每个角色都可以分配一个 "管理角色"。例如:

  • 创建角色 minterminter_admin

  • minter_admin 分配为 minter 角色的管理角色

  • 具有 minter_admin 角色的帐户可以向其他帐户授予/撤销 minter 角色

这允许创建具有命令链和委托权限的复杂组织结构。

角色枚举

系统通过额外的枚举逻辑在存储中跟踪帐户-角色对:

  • 当角色被授予给帐户时,该对被存储并添加到枚举存储

  • 当角色被撤销时,该对从存储和枚举中删除

  • 如果从角色中删除了所有帐户,则辅助存储项目将变为空或 0

角色仅通过它们与帐户的关系存在,因此具有零帐户的角色与从未存在过的角色无法区分。

使用示例

以下是使用 Access Control 模块的简单示例:

use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env};
use stellar_access::access_control::{self as access_control, AccessControl};
use stellar_macros::{has_role, only_admin};

#[contract]
pub struct MyContract;

#[contractimpl]
impl MyContract {
    pub fn __constructor(e: &Env, admin: Address) {
        // 设置合约管理员
        access_control::set_admin(e, &admin);

        // 创建一个 "minter" 角色,其中 admin 作为其管理员
        access_control::set_role_admin_no_auth(e, &symbol_short!("minter"), &symbol_short!("admin"));
    }

    #[only_admin]
    pub fn admin_restricted_function(e: &Env) -> Vec<String> {
        vec![&e, String::from_str(e, "seems sus")]
    }

    // 我们想要宏提供的 `require_auth()`,因为在 `Base::mint` 中没有
    // `require_auth()`。
    #[only_role(caller, "minter")]
    pub fn mint(e: &Env, caller: Address, to: Address, token_id: u32) {
        Base::mint(e, &to, token_id)
    }

    // 允许 minter 或 burner 角色,不在宏中强制执行 `require_auth`
    #[has_any_role(caller, ["minter", "burner"])]
    pub fn multi_role_action(e: &Env, caller: Address) -> String {
        caller.require_auth();
        String::from_str(e, "multi_role_action_success")
    }

    // 允许 minter 或 burner 角色 AND 在宏中强制执行 `require_auth`
    #[only_any_role(caller, ["minter", "burner"])]
    pub fn multi_role_auth_action(e: &Env, caller: Address) -> String {
        String::from_str(e, "multi_role_auth_action_success")
    }
}

收益与权衡

收益

  • 灵活的基于角色的权限系统

  • 分层角色管理

  • 安全的管理员转移流程

  • 管理员可以放弃

  • 易于与过程宏集成

权衡

  • 比 Ownable 等单所有者模型更复杂