访问控制列表(ACL)是一种基于规则的权限管控机制,通过维护主体对资源的操作权限列表,实现对系统资源的细粒度访问控制,在C++系统开发中,我们可以通过面向对象的方式实现一套轻量可用的ACL组件。
ACL核心概念建模
实现ACL前需要先明确核心实体的抽象,通常包含三个部分:权限主体(用户或角色)、资源对象、权限规则。我们可以用结构体分别定义这些实体:
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <set>
// 权限类型枚举,可根据实际需求扩展
enum class Permission {
READ = 1 << 0, // 读权限
WRITE = 1 << 1, // 写权限
EXECUTE = 1 << 2,// 执行权限
DELETE = 1 << 3 // 删除权限
};
// 权限主体结构,支持用户和角色两种类型
struct Principal {
std::string id; // 主体唯一标识
bool is_role; // 是否为角色类型
Principal(std::string pid, bool role) : id(pid), is_role(role) {}
// 重载相等运算符,用于哈希表键值比较
bool operator==(const Principal& other) const {
return id == other.id && is_role == other.is_role;
}
};
// 自定义Principal哈希函数,用于unordered_map存储
struct PrincipalHash {
std::size_t operator()(const Principal& p) const {
return std::hash<std::string>()(p.id) ^ (std::hash<bool>()(p.is_role) << 1);
}
};
// 资源结构,标识被访问的资源
struct Resource {
std::string id; // 资源唯一标识
std::string type; // 资源类型,比如文件、接口等
Resource(std::string rid, std::string rtype) : id(rid), type(rtype) {}
};
ACL核心管理类实现
接下来实现ACL的核心管理类,负责权限规则的增删改查和权限校验逻辑:
class AccessControlList {
private:
// 存储结构:key为资源,value为主体到权限集合的映射
std::unordered_map<std::string, std::unordered_map<Principal, std::set<Permission>, PrincipalHash>> acl_rules;
public:
// 添加权限规则:给指定主体授予对指定资源的某个权限
void add_permission(const Principal& principal, const Resource& resource, Permission perm) {
acl_rules[resource.id][principal].insert(perm);
}
// 移除指定主体对指定资源的某个权限
void remove_permission(const Principal& principal, const Resource& resource, Permission perm) {
auto res_it = acl_rules.find(resource.id);
if (res_it != acl_rules.end()) {
auto prin_it = res_it->second.find(principal);
if (prin_it != res_it->second.end()) {
prin_it->second.erase(perm);
// 如果主体对应权限为空,移除该主体条目
if (prin_it->second.empty()) {
res_it->second.erase(principal);
}
// 如果资源对应所有主体权限为空,移除该资源条目
if (res_it->second.empty()) {
acl_rules.erase(resource.id);
}
}
}
}
// 校验指定主体是否有指定资源的目标权限
bool check_permission(const Principal& principal, const Resource& resource, Permission target_perm) {
auto res_it = acl_rules.find(resource.id);
if (res_it == acl_rules.end()) {
return false; // 没有该资源的任何权限规则
}
auto prin_it = res_it->second.find(principal);
if (prin_it == res_it->second.end()) {
return false; // 该主体没有该资源的任何权限
}
// 校验权限是否存在
return prin_it->second.find(target_perm) != prin_it->second.end();
}
// 获取指定主体对指定资源的所有权限
std::set<Permission> get_permissions(const Principal& principal, const Resource& resource) {
auto res_it = acl_rules.find(resource.id);
if (res_it != acl_rules.end()) {
auto prin_it = res_it->second.find(principal);
if (prin_it != res_it->second.end()) {
return prin_it->second;
}
}
return {};
}
};
功能测试示例
我们可以通过以下测试代码验证ACL实现的正确性:
int main() {
AccessControlList acl;
// 定义主体:用户user1,角色admin
Principal user1("user1", false);
Principal admin_role("admin", true);
// 定义资源:文件file1,接口api1
Resource file1("file1", "file");
Resource api1("api1", "api");
// 给用户user1授予file1的读权限
acl.add_permission(user1, file1, Permission::READ);
// 给admin角色授予file1的读写执行权限
acl.add_permission(admin_role, file1, Permission::READ);
acl.add_permission(admin_role, file1, Permission::WRITE);
acl.add_permission(admin_role, file1, Permission::EXECUTE);
// 给admin角色授予api1的所有权限
acl.add_permission(admin_role, api1, Permission::READ);
acl.add_permission(admin_role, api1, Permission::WRITE);
acl.add_permission(admin_role, api1, Permission::EXECUTE);
acl.add_permission(admin_role, api1, Permission::DELETE);
// 校验权限
std::cout << "user1是否有file1读权限:" << (acl.check_permission(user1, file1, Permission::READ) ? "是" : "否") << std::endl;
std::cout << "user1是否有file1写权限:" << (acl.check_permission(user1, file1, Permission::WRITE) ? "是" : "否") << std::endl;
std::cout << "admin角色是否有file1执行权限:" << (acl.check_permission(admin_role, file1, Permission::EXECUTE) ? "是" : "否") << std::endl;
std::cout << "admin角色是否有api1删除权限:" << (acl.check_permission(admin_role, api1, Permission::DELETE) ? "是" : "否") << std::endl;
// 移除admin角色对file1的写权限
acl.remove_permission(admin_role, file1, Permission::WRITE);
std::cout << "移除后admin角色是否有file1写权限:" << (acl.check_permission(admin_role, file1, Permission::WRITE) ? "是" : "否") << std::endl;
return 0;
}
实现优化方向
上述实现是基础版本,实际使用中可以根据需求扩展优化:
- 支持权限继承:比如角色权限可以继承给用户,减少重复配置
- 支持权限组:将多个权限打包为权限组,方便批量授予
- 增加默认权限规则:当没有匹配的规则时,使用默认允许或默认拒绝策略
- 加入资源层级匹配:支持通配符匹配资源标识,比如给某个目录下的所有文件统一配置权限
- 增加权限过期机制:支持临时权限配置,到时间自动失效
整个实现过程不需要依赖第三方库,仅使用C++标准库就可以完成,开发者可以根据自身系统的权限管控需求调整实体定义和规则逻辑,快速适配不同的业务场景。