6、ABAC (Attribute-Based Access Control) 权限系统详细指南

【ABAC】最强实战:基于.net core + vue2 实现ABAC鉴权模型(附数据库设计和核心代码) 可能是史上最强的.net + vue 全栈实战ABAC,附数据库设计和核心代码 阅读详情

目录

  1. ABAC 核心概念与原理
  2. ABAC vs RBAC 详细对比
  3. ABAC 数据库设计
  4. ABAC 工作流程详解
  5. Java 实现示例(含详细中文注释)
  6. 策略管理与评估
  7. API 使用示例
  8. 性能优化与安全考虑
  9. 测试用例验证

一、ABAC 核心概念与原理

1.1 什么是 ABAC?

ABAC (Attribute-Based Access Control) 基于属性的访问控制是一种动态、细粒度的权限控制模型,它通过评估主体、客体、操作和环境四个维度的属性来做出访问决策。

1.2 ABAC 四大核心要素

要素说明示例
主体(Subject)请求操作的实体用户、设备、应用
客体(Object)被操作的资源文件、API、数据库记录
操作(Action)请求执行的动作读取、写入、删除、执行
环境(Environment)决策时的上下文时间、地点、IP、设备类型

1.3 属性类型详解

1.3.1 主体属性
  • 身份属性:用户ID、用户名、部门、职位、角色
  • 安全属性:安全等级、认证方式、会话状态
  • 业务属性:用户类型、客户等级、账户状态
1.3.2 客体属性
  • 资源属性:资源ID、资源类型、所有者、敏感级别
  • 业务属性:创建时间、状态、关联业务线
  • 安全属性:加密状态、访问频率、风险等级
1.3.3 操作属性
  • 操作类型:READ、WRITE、DELETE、EXECUTE
  • 操作级别:普通操作、敏感操作、管理操作
  • 操作上下文:批量操作、单次操作、定时操作
1.3.4 环境属性
  • 时间属性:当前时间、工作日、节假日
  • 空间属性:IP地址、地理位置、网络环境
  • 设备属性:设备类型、操作系统、安全状态
  • 会话属性:会话ID、认证强度、多因素认证状态

1.4 形象类比

智能门禁系统:

  • 传统门禁(RBAC):刷卡开门,卡的权限是固定的(员工卡只能进办公区)
  • 智能门禁(ABAC):综合判断多个条件
    • 主体:你是张三(部门:财务部,职位:经理)
    • 客体:财务室门(敏感级别:高,所有者:财务总监)
    • 操作:进入(操作类型:物理访问)
    • 环境:工作日上午10点,公司内网IP,已通过指纹认证

只有当所有条件都满足策略要求时,门才会打开。


二、ABAC vs RBAC 详细对比

2.1 核心差异对比表

特性RBACABAC
控制粒度角色级别属性级别(细粒度)
灵活性静态(预定义角色)动态(实时计算)
管理复杂度角色爆炸问题策略管理复杂
适用场景组织架构稳定动态业务场景
性能高(简单查询)中(复杂计算)
可扩展性有限极高
实现复杂度低高

2.2 具体场景对比

场景1:时间限制访问
  • RBAC:无法实现,需要为不同时段创建不同角色
  • ABAC:策略直接包含时间条件
    {
      "condition": "currentTime >= '09:00' && currentTime <= '18:00'"
    }
    
场景2:数据行级权限
  • RBAC:需要为每个数据所有者创建角色
  • ABAC:策略动态比较用户ID和数据所有者ID
    {
      "condition": "subject.userId == object.ownerId"
    }
    
场景3:多因素认证要求
  • RBAC:无法根据认证强度动态调整权限
  • ABAC:策略根据认证方式决定权限
    {
      "condition": "subject.authLevel == 'MFA' || object.sensitivity != 'HIGH'"
    }
    

2.3 选择建议

  • 选择 RBAC:组织架构稳定、权限模型相对固定、性能要求极高
  • 选择 ABAC:需要动态权限、细粒度控制、复杂业务规则、合规要求严格
  • 混合使用:RBAC + ABAC,用 RBAC 管理基础权限,ABAC 处理特殊场景

三、ABAC 数据库设计

3.1 表结构总览

表名说明
abac_policy策略表(核心)
abac_policy_rule策略规则表
abac_subject_attribute主体属性表
abac_object_attribute客体属性表
abac_environment_attribute环境属性表
abac_audit_logABAC审计日志表

3.2 详细表结构

3.2.1 策略表 (abac_policy)
CREATE TABLE `abac_policy` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '策略ID',
  `policy_name` VARCHAR(100) NOT NULL COMMENT '策略名称',
  `policy_description` VARCHAR(500) DEFAULT NULL COMMENT '策略描述',
  `effect` VARCHAR(10) NOT NULL DEFAULT 'ALLOW' COMMENT '策略效果:ALLOW/DENY',
  `priority` INT DEFAULT 0 COMMENT '策略优先级(数值越小优先级越高)',
  `status` TINYINT DEFAULT 1 COMMENT '状态:1-启用,0-禁用',
  `version` INT DEFAULT 1 COMMENT '策略版本',
  `created_by` BIGINT NOT NULL COMMENT '创建人ID',
  `created_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_priority` (`priority`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ABAC策略表';
3.2.2 策略规则表 (abac_policy_rule)
CREATE TABLE `abac_policy_rule` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '规则ID',
  `policy_id` BIGINT NOT NULL COMMENT '所属策略ID',
  `rule_type` VARCHAR(20) NOT NULL COMMENT '规则类型:SUBJECT/OBJECT/ACTION/ENVIRONMENT/COMBINED',
  `attribute_path` VARCHAR(200) NOT NULL COMMENT '属性路径(如:subject.department)',
  `operator` VARCHAR(20) NOT NULL COMMENT '操作符:EQUAL/NOT_EQUAL/GREATER_THAN/LESS_THAN/IN/CONTAINS等',
  `attribute_value` TEXT NOT NULL COMMENT '属性值(JSON格式存储复杂值)',
  `logical_operator` VARCHAR(10) DEFAULT 'AND' COMMENT '逻辑操作符:AND/OR(用于规则组合)',
  `created_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `idx_policy_id` (`policy_id`),
  KEY `idx_rule_type` (`rule_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ABAC策略规则表';
3.2.3 主体属性表 (abac_subject_attribute)
CREATE TABLE `abac_subject_attribute` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '属性ID',
  `subject_type` VARCHAR(20) NOT NULL COMMENT '主体类型:USER/DEVICE/APPLICATION',
  `subject_id` BIGINT NOT NULL COMMENT '主体ID',
  `attribute_name` VARCHAR(50) NOT NULL COMMENT '属性名称',
  `attribute_value` TEXT NOT NULL COMMENT '属性值',
  `attribute_type` VARCHAR(20) NOT NULL COMMENT '属性类型:STRING/INTEGER/BOOLEAN/DATE/TIME',
  `last_updated` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_subject_attr` (`subject_type`, `subject_id`, `attribute_name`),
  KEY `idx_subject` (`subject_type`, `subject_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='主体属性表';
3.2.4 客体属性表 (abac_object_attribute)
CREATE TABLE `abac_object_attribute` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '属性ID',
  `object_type` VARCHAR(50) NOT NULL COMMENT '客体类型:FILE/API/DATABASE_RECORD/RESOURCE',
  `object_id` VARCHAR(100) NOT NULL COMMENT '客体ID(字符串,支持UUID等)',
  `attribute_name` VARCHAR(50) NOT NULL COMMENT '属性名称',
  `attribute_value` TEXT NOT NULL COMMENT '属性值',
  `attribute_type` VARCHAR(20) NOT NULL COMMENT '属性类型:STRING/INTEGER/BOOLEAN/DATE/TIME',
  `last_updated` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_object_attr` (`object_type`, `object_id`, `attribute_name`),
  KEY `idx_object` (`object_type`, `object_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客体属性表';
3.2.5 环境属性表 (abac_environment_attribute)
-- 环境属性通常是动态的,不需要持久化存储
-- 但在某些场景下可能需要预定义环境规则
CREATE TABLE `abac_environment_rule` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '环境规则ID',
  `rule_name` VARCHAR(100) NOT NULL COMMENT '规则名称',
  `attribute_name` VARCHAR(50) NOT NULL COMMENT '环境属性名称:IP_RANGE/TIME_RANGE/LOCATION等',
  `attribute_value` TEXT NOT NULL COMMENT '属性值(JSON格式)',
  `description` VARCHAR(200) DEFAULT NULL COMMENT '描述',
  `status` TINYINT DEFAULT 1 COMMENT '状态:1-启用,0-禁用',
  `created_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `idx_attribute_name` (`attribute_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='环境规则表';
3.2.6 ABAC审计日志表 (abac_audit_log)
CREATE TABLE `abac_audit_log` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '审计日志ID',
  `subject_id` BIGINT NOT NULL COMMENT '主体ID',
  `object_id` VARCHAR(100) NOT NULL COMMENT '客体ID',
  `action` VARCHAR(50) NOT NULL COMMENT '操作',
  `decision` VARCHAR(10) NOT NULL COMMENT '决策结果:ALLOW/DENY',
  `matched_policy_id` BIGINT DEFAULT NULL COMMENT '匹配的策略ID',
  `evaluation_details` JSON DEFAULT NULL COMMENT '评估详情(JSON格式)',
  `request_attributes` JSON DEFAULT NULL COMMENT '请求属性快照',
  `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'IP地址',
  `user_agent` VARCHAR(500) DEFAULT NULL COMMENT '用户代理',
  `evaluation_time` BIGINT NOT NULL COMMENT '评估耗时(毫秒)',
  `created_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `idx_subject` (`subject_id`),
  KEY `idx_object` (`object_id`),
  KEY `idx_decision` (`decision`),
  KEY `idx_created_time` (`created_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ABAC审计日志表';

3.3 示例策略数据

策略1:工作时间访问财务系统
-- 策略记录
INSERT INTO abac_policy (policy_name, policy_description, effect, priority) 
VALUES ('财务系统工作时间访问', '只允许工作时间访问财务系统', 'ALLOW', 10);

-- 策略规则
INSERT INTO abac_policy_rule (policy_id, rule_type, attribute_path, operator, attribute_value) VALUES
(1, 'SUBJECT', 'subject.department', 'EQUAL', '"FINANCE"'),
(1, 'OBJECT', 'object.resourceType', 'EQUAL', '"FINANCE_SYSTEM"'),
(1, 'ENVIRONMENT', 'environment.currentTime', 'GREATER_THAN_EQUAL', '"09:00"'),
(1, 'ENVIRONMENT', 'environment.currentTime', 'LESS_THAN_EQUAL', '"18:00"'),
(1, 'ENVIRONMENT', 'environment.workday', 'EQUAL', 'true');
策略2:数据所有者访问控制
-- 策略记录
INSERT INTO abac_policy (policy_name, policy_description, effect, priority) 
VALUES ('数据所有者访问', '用户只能访问自己创建的数据', 'ALLOW', 20);

-- 策略规则(组合条件)
INSERT INTO abac_policy_rule (policy_id, rule_type, attribute_path, operator, attribute_value, logical_operator) VALUES
(2, 'COMBINED', 'subject.userId == object.ownerId', 'EXPRESSION', 'true', 'AND');

四、ABAC 工作流程详解

4.1 ABAC 决策流程

请求者PEP(策略执行点)PDP(策略决策点)PIP(策略信息点)PRP(策略检索点)Audit发起访问请求发送访问请求(主体,客体,操作,环境)获取适用策略返回策略列表获取缺失属性返回属性值评估策略(逐条匹配)返回决策(ALLOW/DENY)执行访问/拒绝返回默认决策(DENY)拒绝访问alt[找到匹配策略][无匹配策略]记录审计日志请求者PEP(策略执行点)PDP(策略决策点)PIP(策略信息点)PRP(策略检索点)Audit

4.2 核心组件说明

4.2.1 PEP (Policy Enforcement Point) 策略执行点
  • 职责:拦截访问请求,调用PDP进行决策,执行PDP返回的决策结果
  • 位置:API网关、应用拦截器、数据库中间件等
4.2.2 PDP (Policy Decision Point) 策略决策点
  • 职责:接收PEP的请求,评估适用策略,返回访问决策
  • 核心:策略评估引擎
4.2.3 PIP (Policy Information Point) 策略信息点
  • 职责:提供策略评估所需的属性信息
  • 数据源:用户服务、资源服务、环境服务等
4.2.4 PRP (Policy Retrieval Point) 策略检索点
  • 职责:存储和管理策略,为PDP提供适用策略
  • 实现:数据库、文件系统、配置中心等

4.3 策略评估算法

4.3.1 策略匹配流程
  1. 策略筛选:根据请求的主体、客体、操作类型筛选适用策略
  2. 属性获取:从PIP获取策略评估所需的完整属性集
  3. 规则评估:逐条评估策略中的规则条件
  4. 逻辑组合:根据规则间的逻辑操作符组合结果
  5. 优先级排序:按策略优先级排序,返回最高优先级的决策
  6. 默认决策:无匹配策略时返回默认决策(通常为DENY)
4.3.2 策略冲突处理
  • 优先级机制:数值越小优先级越高
  • 拒绝优先:DENY策略优先于ALLOW策略
  • 最近匹配:返回第一个匹配的策略(按优先级排序后)

五、Java 实现示例(含详细中文注释)

5.1 核心实体类

ABAC请求上下文
/**
 * ABAC访问请求上下文
 * 包含PEP发送给PDP的所有信息
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AbacRequestContext {
    /**
     * 主体信息(请求者)
     */
    private Subject subject;
    
    /**
     * 客体信息(被访问的资源)
     */
    private Object object;
    
    /**
     * 操作信息(请求的操作)
     */
    private String action;
    
    /**
     * 环境信息(请求的上下文)
     */
    private Environment environment;
    
    /**
     * 请求时间戳(用于审计)
     */
    private LocalDateTime requestTime;
    
    /**
     * 请求唯一标识(用于跟踪)
     */
    private String requestId;
}
主体、客体、环境实体
/**
 * 主体实体(请求者)
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Subject {
    private Long id;
    private String type; // USER, DEVICE, APPLICATION
    private Map<String, Object> attributes; // 动态属性集合
}

/**
 * 客体实体(被访问的资源)
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Object {
    private String id;
    private String type; // FILE, API, DATABASE_RECORD
    private Map<String, Object> attributes; // 动态属性集合
}

/**
 * 环境实体(请求上下文)
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Environment {
    private Map<String, Object> attributes; // 动态属性集合
    
    public Environment() {
        this.attributes = new HashMap<>();
        // 初始化常用环境属性
        this.attributes.put("currentTime", LocalTime.now());
        this.attributes.put("currentDate", LocalDate.now());
        this.attributes.put("workday", isWorkday());
        this.attributes.put("weekend", !isWorkday());
    }
    
    private boolean isWorkday() {
        DayOfWeek day = LocalDate.now().getDayOfWeek();
        return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY;
    }
}

5.2 策略评估引擎核心实现

/**
 * ABAC策略评估引擎(PDP核心实现)
 * 负责评估策略并返回访问决策
 */
@Service
@Slf4j
public class AbacPolicyEngine {
    
    @Autowired
    private AbacPolicyRepository policyRepository;
    
    @Autowired
    private AbacAttributeService attributeService;
    
    @Autowired
    private AbacAuditService auditService;
    
    /**
     * 评估ABAC访问请求
     * 这是ABAC系统的核心方法
     * 
     * 评估流程:
     * 1. 获取适用的策略列表
     * 2. 补充缺失的属性信息
     * 3. 按优先级排序策略
     * 4. 逐条评估策略
     * 5. 返回第一个匹配策略的决策
     * 6. 记录审计日志
     * 
     * @param requestContext ABAC请求上下文
     * @return 访问决策结果
     */
    public AbacDecision evaluate(AbacRequestContext requestContext) {
        long startTime = System.currentTimeMillis();
        log.debug("开始ABAC策略评估: requestId={}", requestContext.getRequestId());
        
        try {
            // 1. 获取适用的策略列表
            List<AbacPolicy> applicablePolicies = getApplicablePolicies(requestContext);
            log.debug("找到 {} 个适用策略", applicablePolicies.size());
            
            if (applicablePolicies.isEmpty()) {
                // 无适用策略,返回默认拒绝
                AbacDecision decision = AbacDecision.builder()
                        .decision("DENY")
                        .reason("无适用策略")
                        .build();
                logDecision(requestContext, decision, startTime);
                return decision;
            }
            
            // 2. 补充缺失的属性信息
            enrichAttributes(requestContext);
            
            // 3. 按优先级排序策略(数值越小优先级越高)
            applicablePolicies.sort(Comparator.comparingInt(AbacPolicy::getPriority));
            
            // 4. 逐条评估策略
            for (AbacPolicy policy : applicablePolicies) {
                boolean matches = evaluatePolicy(policy, requestContext);
                if (matches) {
                    // 找到匹配策略,返回决策
                    AbacDecision decision = AbacDecision.builder()
                            .decision(policy.getEffect())
                            .matchedPolicyId(policy.getId())
                            .reason("策略匹配: " + policy.getPolicyName())
                            .build();
                    logDecision(requestContext, decision, startTime);
                    return decision;
                }
            }
            
            // 5. 无匹配策略,返回默认拒绝
            AbacDecision decision = AbacDecision.builder()
                    .decision("DENY")
                    .reason("无匹配策略")
                    .build();
            logDecision(requestContext, decision, startTime);
            return decision;
            
        } catch (Exception e) {
            log.error("ABAC策略评估发生异常", e);
            AbacDecision errorDecision = AbacDecision.builder()
                    .decision("DENY")
                    .reason("系统异常: " + e.getMessage())
                    .build();
            logDecision(requestContext, errorDecision, startTime);
            return errorDecision;
        }
    }
    
    /**
     * 获取适用的策略列表
     * 根据请求的基本信息筛选可能适用的策略
     */
    private List<AbacPolicy> getApplicablePolicies(AbacRequestContext requestContext) {
        // 简化实现:返回所有启用的策略
        // 实际项目中可以根据主体类型、客体类型、操作类型进行预筛选
        return policyRepository.findActivePolicies();
    }
    
    /**
     * 补充缺失的属性信息
     * 从PIP(策略信息点)获取策略评估所需的完整属性
     */
    private void enrichAttributes(AbacRequestContext requestContext) {
        // 1. 补充主体属性
        Map<String, Object> subjectAttributes = 
            attributeService.getSubjectAttributes(
                requestContext.getSubject().getType(),
                requestContext.getSubject().getId()
            );
        requestContext.getSubject().getAttributes().putAll(subjectAttributes);
        
        // 2. 补充客体属性
        Map<String, Object> objectAttributes = 
            attributeService.getObjectAttributes(
                requestContext.getObject().getType(),
                requestContext.getObject().getId()
            );
        requestContext.getObject().getAttributes().putAll(objectAttributes);
        
        log.debug("属性补充完成: subjectAttrs={}, objectAttrs={}", 
                subjectAttributes.size(), objectAttributes.size());
    }
    
    /**
     * 评估单个策略是否匹配
     * 
     * @param policy 待评估的策略
     * @param requestContext 请求上下文
     * @return true-策略匹配,false-不匹配
     */
    private boolean evaluatePolicy(AbacPolicy policy, AbacRequestContext requestContext) {
        log.debug("开始评估策略: policyId={}, policyName={}", 
                policy.getId(), policy.getPolicyName());
        
        try {
            // 获取策略的所有规则
            List<AbacPolicyRule> rules = policy.getRules();
            if (CollectionUtils.isEmpty(rules)) {
                return false; // 无规则的策略不匹配
            }
            
            // 评估每条规则
            boolean allRulesMatch = true;
            for (AbacPolicyRule rule : rules) {
                boolean ruleMatches = evaluateRule(rule, requestContext);
                if (!ruleMatches) {
                    allRulesMatch = false;
                    break;
                }
            }
            
            log.debug("策略评估结果: policyId={}, matches={}", policy.getId(), allRulesMatch);
            return allRulesMatch;
            
        } catch (Exception e) {
            log.error("策略评估发生异常: policyId={}", policy.getId(), e);
            return false;
        }
    }
    
    /**
     * 评估单条规则是否匹配
     * 
     * @param rule 待评估的规则
     * @param requestContext 请求上下文
     * @return true-规则匹配,false-不匹配
     */
    private boolean evaluateRule(AbacPolicyRule rule, AbacRequestContext requestContext) {
        try {
            // 1. 解析属性路径,获取实际属性值
            Object actualValue = getAttributeValue(rule.getAttributePath(), requestContext);
            if (actualValue == null) {
                log.debug("属性值为空,规则不匹配: path={}", rule.getAttributePath());
                return false;
            }
            
            // 2. 解析规则期望的属性值
            Object expectedValue = parseAttributeValue(rule.getAttributeValue(), rule.getAttributeType());
            
            // 3. 根据操作符比较值
            boolean matches = compareValues(actualValue, expectedValue, rule.getOperator());
            
            log.debug("规则评估: path={}, actual={}, expected={}, operator={}, matches={}",
                    rule.getAttributePath(), actualValue, expectedValue, rule.getOperator(), matches);
            
            return matches;
            
        } catch (Exception e) {
            log.error("规则评估发生异常: ruleId={}", rule.getId(), e);
            return false;
        }
    }
    
    /**
     * 根据属性路径获取实际属性值
     * 支持嵌套属性路径,如:subject.department
     */
    private Object getAttributeValue(String attributePath, AbacRequestContext requestContext) {
        String[] parts = attributePath.split("\\.");
        if (parts.length != 2) {
            throw new IllegalArgumentException("无效的属性路径: " + attributePath);
        }
        
        String entityType = parts[0]; // subject, object, environment
        String attributeName = parts[1]; // department, resourceId, currentTime
        
        switch (entityType.toLowerCase()) {
            case "subject":
                return requestContext.getSubject().getAttributes().get(attributeName);
            case "object":
                return requestContext.getObject().getAttributes().get(attributeName);
            case "environment":
                return requestContext.getEnvironment().getAttributes().get(attributeName);
            default:
                throw new IllegalArgumentException("不支持的实体类型: " + entityType);
        }
    }
    
    /**
     * 解析属性值(从字符串转换为实际类型)
     */
    private Object parseAttributeValue(String valueStr, String valueType) {
        if (valueStr == null || valueStr.isEmpty()) {
            return null;
        }
        
        try {
            switch (valueType.toLowerCase()) {
                case "string":
                    // 移除JSON字符串的引号
                    if (valueStr.startsWith("\"") && valueStr.endsWith("\"")) {
                        return valueStr.substring(1, valueStr.length() - 1);
                    }
                    return valueStr;
                case "integer":
                    return Integer.parseInt(valueStr);
                case "boolean":
                    return Boolean.parseBoolean(valueStr);
                case "date":
                    return LocalDate.parse(valueStr);
                case "time":
                    return LocalTime.parse(valueStr);
                default:
                    return valueStr;
            }
        } catch (Exception e) {
            log.warn("属性值解析失败: value={}, type={}", valueStr, valueType, e);
            return valueStr;
        }
    }
    
    /**
     * 根据操作符比较两个值
     */
    private boolean compareValues(Object actual, Object expected, String operator) {
        if (actual == null || expected == null) {
            return false;
        }
        
        try {
            switch (operator.toUpperCase()) {
                case "EQUAL":
                    return Objects.equals(actual, expected);
                case "NOT_EQUAL":
                    return !Objects.equals(actual, expected);
                case "GREATER_THAN":
                    return compareComparable(actual, expected) > 0;
                case "GREATER_THAN_EQUAL":
                    return compareComparable(actual, expected) >= 0;
                case "LESS_THAN":
                    return compareComparable(actual, expected) < 0;
                case "LESS_THAN_EQUAL":
                    return compareComparable(actual, expected) <= 0;
                case "IN":
                    // expected 应该是数组或列表
                    if (expected instanceof String) {
                        // 解析JSON数组
                        List<?> expectedList = JsonUtils.parseList((String) expected);
                        return expectedList.contains(actual);
                    }
                    return false;
                case "CONTAINS":
                    if (actual instanceof String && expected instanceof String) {
                        return ((String) actual).contains((String) expected);
                    }
                    return false;
                default:
                    throw new IllegalArgumentException("不支持的操作符: " + operator);
            }
        } catch (Exception e) {
            log.warn("值比较失败: actual={}, expected={}, operator={}", actual, expected, operator, e);
            return false;
        }
    }
    
    /**
     * 比较可比较对象
     */
    @SuppressWarnings("unchecked")
    private int compareComparable(Object actual, Object expected) {
        if (actual instanceof Comparable && expected instanceof Comparable) {
            // 类型转换
            if (actual.getClass() != expected.getClass()) {
                // 尝试转换为相同类型
                if (actual instanceof Number && expected instanceof Number) {
                    Double actualDouble = ((Number) actual).doubleValue();
                    Double expectedDouble = ((Number) expected).doubleValue();
                    return actualDouble.compareTo(expectedDouble);
                }
            }
            return ((Comparable) actual).compareTo(expected);
        }
        throw new IllegalArgumentException("对象不可比较: " + actual.getClass() + ", " + expected.getClass());
    }
    
    /**
     * 记录决策审计日志
     */
    private void logDecision(AbacRequestContext requestContext, AbacDecision decision, long startTime) {
        long evaluationTime = System.currentTimeMillis() - startTime;
        
        AbacAuditLog auditLog = AbacAuditLog.builder()
                .subjectId(requestContext.getSubject().getId())
                .objectId(requestContext.getObject().getId())
                .action(requestContext.getAction())
                .decision(decision.getDecision())
                .matchedPolicyId(decision.getMatchedPolicyId())
                .evaluationDetails(buildEvaluationDetails(requestContext, decision))
                .requestAttributes(buildRequestAttributesSnapshot(requestContext))
                .ipAddress(getIpAddress(requestContext))
                .userAgent(getUserAgent(requestContext))
                .evaluationTime(evaluationTime)
                .build();
        
        auditService.logAudit(auditLog);
        
        log.info("ABAC决策完成: requestId={}, decision={}, time={}ms", 
                requestContext.getRequestId(), decision.getDecision(), evaluationTime);
    }
    
    /**
     * 构建评估详情
     */
    private String buildEvaluationDetails(AbacRequestContext requestContext, AbacDecision decision) {
        Map<String, Object> details = new HashMap<>();
        details.put("requestId", requestContext.getRequestId());
        details.put("reason", decision.getReason());
        details.put("subjectType", requestContext.getSubject().getType());
        details.put("objectType", requestContext.getObject().getType());
        return JsonUtils.toJson(details);
    }
    
    /**
     * 构建请求属性快照
     */
    private String buildRequestAttributesSnapshot(AbacRequestContext requestContext) {
        Map<String, Object> snapshot = new HashMap<>();
        snapshot.put("subject", requestContext.getSubject().getAttributes());
        snapshot.put("object", requestContext.getObject().getAttributes());
        snapshot.put("environment", requestContext.getEnvironment().getAttributes());
        snapshot.put("action", requestContext.getAction());
        return JsonUtils.toJson(snapshot);
    }
    
    /**
     * 获取IP地址(简化实现)
     */
    private String getIpAddress(AbacRequestContext requestContext) {
        // 实际项目中从请求上下文获取
        return "127.0.0.1";
    }
    
    /**
     * 获取用户代理(简化实现)
     */
    private String getUserAgent(AbacRequestContext requestContext) {
        return "ABAC-Client";
    }
}

5.3 策略信息点(PIP)实现

/**
 * ABAC属性服务(PIP实现)
 * 负责提供策略评估所需的属性信息
 */
@Service
@Slf4j
public class AbacAttributeService {
    
    @Autowired
    private SubjectAttributeMapper subjectAttributeMapper;
    
    @Autowired
    private ObjectAttributeMapper objectAttributeMapper;
    
    /**
     * 获取主体属性
     * 
     * @param subjectType 主体类型(USER/DEVICE/APPLICATION)
     * @param subjectId 主体ID
     * @return 主体属性映射
     */
    public Map<String, Object> getSubjectAttributes(String subjectType, Long subjectId) {
        log.debug("获取主体属性: type={}, id={}", subjectType, subjectId);
        
        List<SubjectAttribute> attributes = 
            subjectAttributeMapper.findBySubject(subjectType, subjectId);
        
        Map<String, Object> attributeMap = new HashMap<>();
        for (SubjectAttribute attr : attributes) {
            Object value = parseAttributeValue(attr.getAttributeValue(), attr.getAttributeType());
            attributeMap.put(attr.getAttributeName(), value);
        }
        
        return attributeMap;
    }
    
    /**
     * 获取客体属性
     * 
     * @param objectType 客体类型(FILE/API/DATABASE_RECORD)
     * @param objectId 客体ID
     * @return 客体属性映射
     */
    public Map<String, Object> getObjectAttributes(String objectType, String objectId) {
        log.debug("获取客体属性: type={}, id={}", objectType, objectId);
        
        List<ObjectAttribute> attributes = 
            objectAttributeMapper.findByObject(objectType, objectId);
        
        Map<String, Object> attributeMap = new HashMap<>();
        for (ObjectAttribute attr : attributes) {
            Object value = parseAttributeValue(attr.getAttributeValue(), attr.getAttributeType());
            attributeMap.put(attr.getAttributeName(), value);
        }
        
        return attributeMap;
    }
    
    /**
     * 解析属性值(复用策略引擎的解析逻辑)
     */
    private Object parseAttributeValue(String valueStr, String valueType) {
        // 复用策略引擎的解析逻辑
        // 实际项目中可以提取为公共方法
        if (valueStr == null || valueStr.isEmpty()) {
            return null;
        }
        
        switch (valueType.toLowerCase()) {
            case "string":
                if (valueStr.startsWith("\"") && valueStr.endsWith("\"")) {
                    return valueStr.substring(1, valueStr.length() - 1);
                }
                return valueStr;
            case "integer":
                return Integer.parseInt(valueStr);
            case "boolean":
                return Boolean.parseBoolean(valueStr);
            case "date":
                return LocalDate.parse(valueStr);
            case "time":
                return LocalTime.parse(valueStr);
            default:
                return valueStr;
        }
    }
}

六、策略管理与评估

6.1 策略DSL设计

/**
 * 策略DSL示例(简化版)
 * 实际项目中可以使用更强大的表达式引擎如MVEL、SpEL
 */
public class PolicyDslExample {
    
    /**
     * 策略1:财务部门工作时间访问财务系统
     */
    public static final String FINANCE_POLICY = 
        "subject.department == 'FINANCE' && " +
        "object.resourceType == 'FINANCE_SYSTEM' && " +
        "environment.currentTime >= '09:00' && " +
        "environment.currentTime <= '18:00' && " +
        "environment.workday == true";
    
    /**
     * 策略2:数据所有者访问
     */
    public static final String OWNER_POLICY = 
        "subject.userId == object.ownerId";
    
    /**
     * 策略3:高敏感数据需要MFA认证
     */
    public static final String SENSITIVE_DATA_POLICY = 
        "object.sensitivity == 'HIGH' ? subject.authLevel == 'MFA' : true";
}

6.2 策略版本管理

/**
 * 策略版本管理服务
 */
@Service
public class PolicyVersionService {
    
    /**
     * 创建策略新版本
     */
    public AbacPolicy createNewVersion(AbacPolicy currentPolicy, AbacPolicyUpdateRequest updateRequest) {
        AbacPolicy newPolicy = new AbacPolicy();
        newPolicy.setPolicyName(currentPolicy.getPolicyName());
        newPolicy.setPolicyDescription(updateRequest.getDescription());
        newPolicy.setEffect(updateRequest.getEffect());
        newPolicy.setPriority(updateRequest.getPriority());
        newPolicy.setVersion(currentPolicy.getVersion() + 1);
        newPolicy.setCreatedBy(updateRequest.getOperatorId());
        
        // 复制并更新规则
        List<AbacPolicyRule> newRules = updateRequest.getRules().stream()
                .map(rule -> convertToRule(rule, newPolicy.getId()))
                .collect(Collectors.toList());
        newPolicy.setRules(newRules);
        
        return policyRepository.save(newPolicy);
    }
    
    /**
     * 回滚到指定版本
     */
    public AbacPolicy rollbackToVersion(Long policyId, Long version) {
        AbacPolicy targetVersion = policyRepository.findByPolicyIdAndVersion(policyId, version);
        if (targetVersion == null) {
            throw new BusinessException("指定版本不存在");
        }
        
        // 创建新版本作为当前版本
        AbacPolicy rolledBack = new AbacPolicy();
        rolledBack.setPolicyName(targetVersion.getPolicyName());
        rolledBack.setPolicyDescription(targetVersion.getPolicyDescription() + " [回滚]");
        rolledBack.setEffect(targetVersion.getEffect());
        rolledBack.setPriority(targetVersion.getPriority());
        rolledBack.setVersion(targetVersion.getVersion() + 1);
        rolledBack.setCreatedBy(SecurityContext.getCurrentUserId());
        rolledBack.setRules(targetVersion.getRules());
        
        return policyRepository.save(rolledBack);
    }
}

七、API 使用示例

7.1 ABAC权限检查API

/**
 * ABAC权限检查Controller
 */
@RestController
@RequestMapping("/api/abac")
public class AbacController {
    
    @Autowired
    private AbacPolicyEngine policyEngine;
    
    /**
     * 检查ABAC权限
     * 
     * 请求示例:
     * POST /api/abac/check-permission
     * {
     *   "subject": {
     *     "id": 1001,
     *     "type": "USER",
     *     "attributes": {
     *       "department": "FINANCE",
     *       "position": "MANAGER"
     *     }
     *   },
     *   "object": {
     *     "id": "finance-system-001",
     *     "type": "FINANCE_SYSTEM",
     *     "attributes": {
     *       "sensitivity": "HIGH",
     *       "resourceType": "FINANCE_SYSTEM"
     *     }
     *   },
     *   "action": "ACCESS",
     *   "environment": {
     *     "attributes": {
     *       "ipAddress": "192.168.1.100",
     *       "deviceType": "DESKTOP"
     *     }
     *   }
     * }
     */
    @PostMapping("/check-permission")
    public Result<AbacDecision> checkPermission(@RequestBody @Valid AbacCheckRequest request) {
        // 构建ABAC请求上下文
        AbacRequestContext context = AbacRequestContext.builder()
                .subject(request.getSubject())
                .object(request.getObject())
                .action(request.getAction())
                .environment(request.getEnvironment() != null ? 
                           request.getEnvironment() : new Environment())
                .requestTime(LocalDateTime.now())
                .requestId(UUID.randomUUID().toString())
                .build();
        
        // 执行策略评估
        AbacDecision decision = policyEngine.evaluate(context);
        
        return Result.success(decision);
    }
    
    /**
     * 简化权限检查(基于当前用户和标准资源)
     */
    @GetMapping("/has-access")
    public Result<Boolean> hasAccess(@RequestParam String resourceId, 
                                   @RequestParam String action) {
        // 获取当前用户
        Long currentUserId = getCurrentUserId();
        Subject currentUser = buildCurrentUserSubject(currentUserId);
        
        // 构建资源对象
        Object resource = buildResourceObject(resourceId);
        
        // 构建请求上下文
        AbacRequestContext context = AbacRequestContext.builder()
                .subject(currentUser)
                .object(resource)
                .action(action)
                .environment(new Environment())
                .requestTime(LocalDateTime.now())
                .requestId(UUID.randomUUID().toString())
                .build();
        
        // 执行评估
        AbacDecision decision = policyEngine.evaluate(context);
        
        return Result.success("ALLOW".equals(decision.getDecision()));
    }
}

7.2 策略管理API

/**
 * ABAC策略管理Controller
 */
@RestController
@RequestMapping("/api/abac/policies")
public class AbacPolicyController {
    
    @Autowired
    private AbacPolicyService policyService;
    
    /**
     * 创建新策略
     */
    @PostMapping
    public Result<AbacPolicy> createPolicy(@RequestBody @Valid CreatePolicyRequest request) {
        AbacPolicy policy = policyService.createPolicy(request);
        return Result.success(policy);
    }
    
    /**
     * 更新策略
     */
    @PutMapping("/{policyId}")
    public Result<AbacPolicy> updatePolicy(@PathVariable Long policyId, 
                                         @RequestBody @Valid UpdatePolicyRequest request) {
        AbacPolicy policy = policyService.updatePolicy(policyId, request);
        return Result.success(policy);
    }
    
    /**
     * 获取策略详情
     */
    @GetMapping("/{policyId}")
    public Result<AbacPolicy> getPolicy(@PathVariable Long policyId) {
        AbacPolicy policy = policyService.getPolicy(policyId);
        return Result.success(policy);
    }
    
    /**
     * 测试策略(模拟评估)
     */
    @PostMapping("/{policyId}/test")
    public Result<PolicyTestResult> testPolicy(@PathVariable Long policyId,
                                             @RequestBody @Valid PolicyTestRequest request) {
        PolicyTestResult result = policyService.testPolicy(policyId, request);
        return Result.success(result);
    }
}

八、性能优化与安全考虑

8.1 性能优化策略

缓存策略
/**
 * ABAC缓存服务
 */
@Service
public class AbacCacheService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 策略缓存(1小时)
    private static final String POLICY_CACHE_KEY = "abac:policies";
    
    // 属性缓存(10分钟)
    private static final String ATTRIBUTE_CACHE_KEY = "abac:attributes:%s:%s:%s"; // type:id:name
    
    // 决策缓存(5分钟,用于重复请求)
    private static final String DECISION_CACHE_KEY = "abac:decision:%s"; // request hash
    
    /**
     * 缓存策略
     */
    public void cachePolicies(List<AbacPolicy> policies) {
        redisTemplate.opsForValue().set(POLICY_CACHE_KEY, policies, 1, TimeUnit.HOURS);
    }
    
    /**
     * 获取缓存的策略
     */
    public List<AbacPolicy> getCachedPolicies() {
        return (List<AbacPolicy>) redisTemplate.opsForValue().get(POLICY_CACHE_KEY);
    }
    
    /**
     * 缓存属性
     */
    public void cacheAttribute(String type, String id, String name, Object value) {
        String key = String.format(ATTRIBUTE_CACHE_KEY, type, id, name);
        redisTemplate.opsForValue().set(key, value, 10, TimeUnit.MINUTES);
    }
    
    /**
     * 获取缓存的属性
     */
    public Object getCachedAttribute(String type, String id, String name) {
        String key = String.format(ATTRIBUTE_CACHE_KEY, type, id, name);
        return redisTemplate.opsForValue().get(key);
    }
}
策略预筛选
/**
 * 策略预筛选器
 * 根据请求基本信息快速筛选适用策略
 */
@Component
public class PolicyPreFilter {
    
    /**
     * 预筛选适用策略
     */
    public List<AbacPolicy> preFilterPolicies(AbacRequestContext requestContext) {
        String subjectType = requestContext.getSubject().getType();
        String objectType = requestContext.getObject().getType();
        String action = requestContext.getAction();
        
        // 从缓存或索引中快速获取适用策略
        return policyIndexService.findPoliciesByCriteria(subjectType, objectType, action);
    }
}

8.2 安全考虑

策略安全
  • 策略验证:防止策略注入攻击
  • 策略沙箱:在安全环境中执行策略评估
  • 策略审计:记录所有策略变更
属性安全
  • 属性验证:验证属性值的合法性
  • 属性加密:敏感属性加密存储
  • 属性脱敏:审计日志中的敏感属性脱敏
决策安全
  • 拒绝优先:默认拒绝未明确允许的访问
  • 最小权限:策略遵循最小权限原则
  • 异常处理:异常情况下返回拒绝决策

九、测试用例验证

9.1 策略评估测试

@SpringBootTest
class AbacPolicyEngineTest {
    
    @Autowired
    private AbacPolicyEngine policyEngine;
    
    @Test
    void testFinanceSystemAccessPolicy() {
        // 准备数据:财务部门用户在工作时间访问财务系统
        AbacRequestContext context = AbacRequestContext.builder()
                .subject(Subject.builder()
                        .id(1001L)
                        .type("USER")
                        .attributes(Map.of("department", "FINANCE"))
                        .build())
                .object(Object.builder()
                        .id("finance-001")
                        .type("FINANCE_SYSTEM")
                        .attributes(Map.of("resourceType", "FINANCE_SYSTEM"))
                        .build())
                .action("ACCESS")
                .environment(new Environment()) // 工作日上午
                .requestTime(LocalDateTime.now())
                .requestId("test-001")
                .build();
        
        // 执行评估
        AbacDecision decision = policyEngine.evaluate(context);
        
        // 验证结果
        assertEquals("ALLOW", decision.getDecision());
        assertNotNull(decision.getMatchedPolicyId());
    }
    
    @Test
    void testFinanceSystemAccessOutsideWorkHours() {
        // 准备数据:财务部门用户在非工作时间访问财务系统
        Environment environment = new Environment();
        environment.getAttributes().put("currentTime", LocalTime.of(20, 0)); // 晚上8点
        
        AbacRequestContext context = AbacRequestContext.builder()
                .subject(Subject.builder()
                        .id(1001L)
                        .type("USER")
                        .attributes(Map.of("department", "FINANCE"))
                        .build())
                .object(Object.builder()
                        .id("finance-001")
                        .type("FINANCE_SYSTEM")
                        .attributes(Map.of("resourceType", "FINANCE_SYSTEM"))
                        .build())
                .action("ACCESS")
                .environment(environment)
                .requestTime(LocalDateTime.now())
                .requestId("test-002")
                .build();
        
        // 执行评估
        AbacDecision decision = policyEngine.evaluate(context);
        
        // 验证结果:应该被拒绝
        assertEquals("DENY", decision.getDecision());
    }
    
    @Test
    void testDataOwnerAccessPolicy() {
        // 准备数据:用户访问自己创建的数据
        AbacRequestContext context = AbacRequestContext.builder()
                .subject(Subject.builder()
                        .id(1001L)
                        .type("USER")
                        .attributes(Map.of("userId", 1001L))
                        .build())
                .object(Object.builder()
                        .id("data-001")
                        .type("DATABASE_RECORD")
                        .attributes(Map.of("ownerId", 1001L))
                        .build())
                .action("READ")
                .environment(new Environment())
                .requestTime(LocalDateTime.now())
                .requestId("test-003")
                .build();
        
        // 执行评估
        AbacDecision decision = policyEngine.evaluate(context);
        
        // 验证结果
        assertEquals("ALLOW", decision.getDecision());
    }
}

9.2 审计日志测试

@Test
void testAuditLogRecording() {
    // 执行权限检查
    AbacRequestContext context = createTestContext();
    AbacDecision decision = policyEngine.evaluate(context);
    
    // 查询审计日志
    List<AbacAuditLog> logs = auditLogService.getRecentAuditLogs(context.getSubject().getId(), 1);
    assertEquals(1, logs.size());
    
    AbacAuditLog log = logs.get(0);
    assertEquals(context.getObject().getId(), log.getObjectId());
    assertEquals(decision.getDecision(), log.getDecision());
    assertTrue(log.getEvaluationTime() > 0);
    assertNotNull(log.getEvaluationDetails());
}

总结

ABAC (Attribute-Based Access Control) 是一种强大的动态权限控制模型,通过评估主体、客体、操作和环境四个维度的属性来做出细粒度的访问决策。

ABAC 核心优势

  1. 动态性:实时计算权限,适应复杂业务场景
  2. 细粒度:支持数据行级、字段级权限控制
  3. 灵活性:无需预定义角色,策略可动态调整
  4. 可扩展性:轻松添加新的属性和策略

适用场景

  • 复杂业务规则:需要基于多种条件动态判断权限
  • 数据安全:行级数据权限、敏感数据保护
  • 合规要求:GDPR、HIPAA等法规要求的精细权限控制
  • 多租户SaaS:复杂的租户间数据隔离需求

实施建议

  1. 渐进式实施:从关键场景开始,逐步扩展
  2. 性能监控:重点关注策略评估的响应时间
  3. 策略管理:建立完善的策略版本管理和测试机制
  4. 审计合规:确保所有决策都有完整的审计记录

ABAC 虽然实现复杂度较高,但对于需要精细化权限控制的企业级应用来说,是值得投资的权限模型选择。

基于属性的访问控制模型ABAC 针对传统访问控制模型难以解决的动态、细粒度访问控制问题,研究人员提出了基于属性的访问控制模型(attribute-based access control,简称ABAC).ABAC 模型基于实体属性而不是用户身份来判决允许或拒绝用户对 资源的访问控制请求.ABAC 模型的核心要素包括主体、资源、操作以及环境约束,这些要素统一使用属性和属性值来进行表示,属性间的关系可以根据访问控制需求进行灵活的设置,提高了访问控制策略语义的表达能力和模型的灵活性,并且能够将其他访问控制模型中权限、安全标签、角色等概念用属性来 阅读详情

相关推荐

ABAC - 基于属性的访问控制 - 复杂场景下访问控制解决之道

引言 引言 在一个典型的软件开发场景中,你作为一名开发人员加入到某个项目后,假设是“超人组”,你往往需要访问这个项目的代码库然后才能开始工作。当你的 Team Lead 将你加入 Git Organization 后,你自然可以访问到“超人组”的代码仓库,然后就可以愉快的进行开发工作了。但是,当你的任务完成后,可能你需要参与另一个项目,你自然就没有权利去访问“超人组”的代码库,所以你的 TL 会将...

Yuchen 的博客 2万+

Spring Expression Language(SpEL)实现ABAC鉴权模型, 动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限

基于ABAC访问控制动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限

小魏的奇妙世界 4403

SpringBoot3集成ABAC实现动态权限控制

访问控制是分布式系统安全的核心机制,其中ABAC(基于属性的访问控制)通过动态评估主体、资源、操作和环境四大维度属性,实现比传统RBAC更细粒度的权限管理。其技术原理是将策略规则与运行时属性进行匹配,利用策略引擎实时决策。在SpringBoot3中结合Spring Security 6,开发者可以高效实现ABAC方案,特别适合医疗系统、金融交易等需要动态权限控制的场景。本文通过SpringBoot3集成示例,展示如何利用属性拦截器、策略决策点等核心组件构建ABAC系统,并分享策略缓存、属性预加载等性能优化技

weixin_33895516的博客 394

权限系统设计详解(三):ABAC 基于属性的访问控制

ABAC(Attribute-Based Access Control,基于属性的访问控制)是一种灵活的访问控制机制,可以根据多个属性来控制用户对资源的访问。这些属性可以是用户属性(如职位、年龄、部门)、资源属性(如文档分类、创建日期)、环境属性(如访问时间、网络位置)和行为属性(如读取、写入、执行)等。ABAC 通过定义一系列的访问策略,这些策略基于属性进行评估,以决定是否允许用户执行特定的操作。ABAC 提供了比传统的访问控制模型(如基于角色的访问控制 RBAC)更高的灵活性和更细的粒度。

路多辛的所思所想 1万+

Spring Security授权进阶:从RBAC到ABAC的实战指南

访问控制是系统安全的核心,它决定了用户能访问哪些资源。其基本原理是通过验证用户身份后,依据预设规则进行权限判定。在技术实现上,基于角色的访问控制(RBAC)通过将权限关联角色来管理,模型简单但粒度较粗。而基于属性的访问控制(ABAC)则通过动态评估主体、资源、操作和环境等多维属性,能实现更精细、更灵活的权限管控,技术价值在于能完美适配复杂多变的业务规则。在实际应用场景中,例如内容管理系统或企业级应用,常需结合两者,实现如“管理员可管理所有内容,普通用户仅能操作所属数据”这类需求。本文聚焦于利用Spring

cuixie2370的博客 675

RBAC与ABAC混合权限模型在AI平台中的设计与SpringBoot实践

访问控制是保障信息系统安全与数据隐私的核心技术,其核心原理是确保合法用户在适当的上下文中对特定资源执行授权操作。从基础的RBAC(基于角色的访问控制)模型到更灵活的ABAC(基于属性的访问控制)模型,权限管理技术不断演进,旨在平衡管理的便捷性与控制的精细度。在微服务与AI驱动的复杂业务场景下,单一模型往往难以应对动态、细粒度的授权需求。RBAC+ABAC混合模型应运而生,它通过分层设计,让RBAC负责粗粒度的静态权限管理,而ABAC则处理基于多重属性(如用户部门、资源敏感度、访问时间、IP地址)的动态策略决

weixin_34310369的博客 416

Attribute-Based Access Control with Spring Security 项目推荐

Attribute-Based Access Control with Spring Security 项目推荐 1. 项目基础介绍与主要编程语言 本项目是一个开源的Attribute-Based Access Control(ABAC)系统,基于Spring Security框架进行开发。ABAC是一种访问控制 paradigm,它通过分析用户的属性、资源的属性以及环境的属性来决定是否授权用户对...

gitblog_00054的博客 324

WSL2离线安装Ubuntu终极指南:绕过Microsoft Store慢速下载(附最新22.04 LTS离线包)

本文提供WSL2离线安装Ubuntu 22.04 LTS的完整指南,帮助开发者绕过Microsoft Store下载慢的问题。通过PowerShell命令配置环境、获取离线安装包并完成安装,同时包含初始配置、资源优化及常见问题解决方案,助您快速搭建高效的Linux开发环境。

c8d9e0f1的博客 898

How to Implement Attribute-based Access Control (ABAC) in Python3

#Python #ABAC

yuguo_im的博客 549

LVGL仪表盘实战:5分钟用lv_meter打造汽车仪表UI(附完整代码)

本文详细介绍了如何使用LVGL的lv_meter组件在5分钟内构建专业汽车仪表盘UI。从环境配置、刻度定制到指针动画和性能优化,提供完整代码示例和实战技巧,帮助开发者快速实现嵌入式设备上的高效仪表盘设计。

k5l6m的博客 417

C/C++ 计算程序运行的时间

C/C++计算程序执行时间的方法,精度依次增加,推荐度也依次增加 1.#include <time.h> clock_t start, finish; double process_interval ; start=clock(); process(); //要计时的程序 finish=clock(); process_interval =(double)(finish-star...

stu_shanghui的博客 1020

[Cloud Computing]Mechanisms: Attribute-Based Access Control System

Attribute-Based Access Control System Attribute-based access control (ABAC) is an access control method where consumer requests to access or perform operations on resources are granted or denied

zjysource的专栏 970

MATLAB闪退别慌!5分钟搞定Windows系统预设文件修复(附详细截图)

本文针对MATLAB在Windows系统下频繁闪退的问题,提供了快速有效的解决方案。核心在于修复或重置损坏的MATLAB预设文件,通过图文并茂的五步法,指导用户定位AppData目录、重命名预设文件夹,从而让MATLAB自动生成全新配置以解决闪退。文章还涵盖了问题诊断、设置备份及进阶排查方法,帮助用户彻底根除启动故障。

weixin_29234423的博客 925

Casbin之ABAC

【代码】Casbin之ABAC。

qq_53267860的博客 346

四旋翼飞行器建模(一)

四旋翼飞行器的姿态运动学和姿态动力学建模方法。

加斯顿工程师的博客 685

SAP 系统中的数字签名解决方案及应用案例分析

在当前企业信息化及数字化转型的大背景下,数据安全与身份认证显得尤为重要。数字签名技术作为保障数据真实性和完整性的重要手段,在 SAP 系统中得到了广泛应用。本文将详细探讨 SAP 系统中部分应用场景如何利用数字签名技术满足业务需求,涵盖 SAP Single Sign-On、质量管理、过程工业生产计划以及 SAP ArchiveLink 内容服务器等方面,力求通过深入解读,帮助读者更好地理解和应用这一关键技术。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 526

ABAC

引子:ABAC是一种属性的集合体对另外一种属性的集合体发起访问,问题:如何进行这种属性关联的计算 引子:ABAC是一种属性的集合体对另外一种属性的集合体发起访问,问题:如何对这种属性进行通用的描述 ...

12Dong的博客 855

【网络协议】【TSN】精讲TSN工作原理!图解超赞超详细!!!

TSN有一个服务等级(class of service,CoS)的概念。对TSN网络而言,不同优先级的服务对应图3中的PCP码。3位PCP码定义了0(最低)~7(最高)这8个优先级,传输类型分别对应基础、最大努力、卓越努力、严苛应用、延时和抖动小于100 ms的视频、延时和抖动小于10 ms的音频、内部网络控制、网络控制。其会对网络场景进行不同的匹配,是后续调度、配置设计中会考虑到的数据流调度因素。

风云说通信 2627

LoopAuth 2.X版本发布——这可能是你第一次使用ABAC鉴权

LoopAuth 发布已经有些时日了,在 LoopAuth 1.X 版本中,一直使用 Rbac 的鉴权方式。 LoopAuth 这个项目在创建初期,就已经思考加入 ABAC 的鉴权模式。 9 月份摆烂一个月后,LoopAuth 2.X 版本现在已发布: 重构完成,加入 ABAC 鉴权模式,将原有核心模块拆分为 Session、RBAC、ABAC 三块。

weixin_43838961的博客 427

光学测量仿真软件:Zygo_(5).Zygo的数据处理与分析方法

通过上述综合案例,我们可以看到Zygo中的数据处理与分析方法是如何一步一步应用于实际数据的。从数据导入到预处理,再到滤波、表面分析、缺陷检测和数据可视化,每一步都至关重要,最终确保了数据的准确性和可靠性。处理后的数据还可以导出为多种格式,便于在其他软件中进行进一步的处理或报告。希望这个案例能够帮助您更好地理解和应用Zygo中的数据处理与分析方法。

kkchenjj的博客 946

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Arcana权限管理框架:从RBAC到ABAC的实战指南

权限管理是现代应用开发中的核心安全机制,其核心目标是控制用户对系统资源的访问。从基础的RBAC(基于角色的访问控制)模型到更灵活的ABAC(基于属性的访问控制)模型,权限系统不断演进以满足复杂业务场景的需求。这些技术通过将权限逻辑与业务代码解耦,显著提升了系统的安全性和可维护性,在企业管理后台、SaaS平台和微服务架构中具有广泛应用价值。本文以开源框架Arcana为例,深入解析如何结合RBAC的简洁性和ABAC的动态性,通过声明式策略实现精细化的权限控制,并分享在性能优化和微服务架构下的实战经验。

weixin_33713707的博客 822

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

论文笔记:A Novel Attribute-Based Access Control Scheme Using Blockchain for IoT

一、基本信息 论文题目:《A Novel Attribute-Based Access Control Scheme Using Blockchain for IoT》 发表时间:IEEE Access 2019 论文作者及单位: 二、摘要 随着智能设备数量的急剧增加,物联网近年来得到了越来越多的关注和快速发展。它有效地将物理世界与因特网结合在现有的网络基础设施上,以便于在智能...

qq_35771020的博客 1568

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

ABAC 数据访问控制

ABAC 即基于属性的访问控制(Attribute-Based Access Control)。在这种模型中,访问决策是基于主体(如用户、进程等)、客体(如数据、资源等)、环境(如时间、地点等)以及操作(如读取、写入、删除等)的属性来确定的。例如,一个用户能否访问特定的数据,不仅取决于其身份(主体属性),还可能取决于当前的时间(环境属性)、数据的敏感性(客体属性)以及所需执行的操作类型(操作属性)。

weixin_43156294的博客 1900

AccessGuard v0.5:ABAC 属性模型 — TypeScript 联合类型与 Discriminated Union 深度实战

Subject(主体):发起访问请求的实体,通常对应已认证用户。// Subject 属性的抽象基类型// 安全许可级别 1-5Resource(资源):被访问的目标实体。// Resource 属性的抽象基类型Action(操作):对资源执行的具体操作。// Action 操作类型Environment(环境):访问请求发生的上下文。// Environment 属性策略条件(Policy Condition)Policy(策略)

我的博客 447

Web 安全视角下的权限系统设计模型:DAC、MAC、RBAC 与 ABAC 全解析

在 Web 安全学习与实战中,理解"权限是如何被设计出来的"是分析越权漏洞、评估认证授权体系的基础。本指南以 Learn-Web-Hacking 仓库的[权限系统设计模型](https://link.gitcode.com/i/5e0c0caad9c5f5a02b583a2414fff1dc)一章为主线,系统梳理自主访问控制(DAC)、强制访问控制(MAC)、基于角色的访问控制(RBAC)与基于属

gitblog_00782的博客 437

【Java ABAC权限控制实战指南】:手把手教你搭建细粒度访问控制体系

掌握Java ABAC权限控制核心方法,解决复杂场景下的细粒度访问控制难题。提供完整Java ABAC配置示例,涵盖策略定义、属性规则与执行流程,支持动态授权与高扩展性设计,适用于微服务与企业级系统,值得收藏。

LiteCompile的博客 1074
上一篇: 5、RBAC3 权限系统详细设计与实现指南(RBAC1+RBAC2组合 + 完整审计)
下一篇: Spring Boot 接口开发设计原则与最佳实践指南
龙茶清欢
博客等级 码龄7年 3720粉丝 375原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值