spring Security对RBAC及其ABAC的支持使用

news2025/6/10 18:06:47

RBAC (基于角色的访问控制)

RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。

RBAC 核心实现

1. 数据库设计
users           roles          permissions
-------         ------        ------------
id              id            id
username        name          name
password        description   url
...                          method
                              description

user_roles      role_permissions
-----------     ---------------
user_id         role_id
role_id         permission_id
2. Spring Security 配置
@Configuration
@EnableWebSecurity
public class RbacSecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
            .antMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .logout();
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        // 从数据库加载用户及其角色
        return username -> {
            User user = userRepository.findByUsername(username);
            return org.springframework.security.core.userdetails.User
                .withUsername(user.getUsername())
                .password(user.getPassword())
                .roles(user.getRoles().stream().map(Role::getName).toArray(String[]::new))
                .build();
        };
    }
}
3. 动态 RBAC 实现
@Service
public class DynamicRbacService {
    
    public boolean hasPermission(Authentication authentication, String url, String method) {
        return authentication.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .anyMatch(permission -> {
                // 从数据库或缓存检查权限
                return permissionRepository.existsByRoleAndUrlAndMethod(
                    permission, url, method);
            });
    }
}

ABAC (基于属性的访问控制)

ABAC (Attribute-Based Access Control) 是更灵活的权限模型,它基于用户属性、资源属性、环境属性等做决策。

ABAC 核心实现

1. 策略规则示例
{
  "name": "编辑文档策略",
  "description": "允许文档所有者在工作时间内编辑自己的文档",
  "target": {
    "resource.type": "document",
    "action": "edit"
  },
  "condition": {
    "user.id == resource.owner_id",
    "time >= '09:00' && time <= '18:00'"
  },
  "effect": "allow"
}
2. Spring Security ABAC 实现

@Component
public class AbacPermissionEvaluator implements PermissionEvaluator {

    @Autowired
    private PolicyEnforcement policyEnforcement;

    @Override
    public boolean hasPermission(Authentication authentication, 
                               Object targetDomainObject, 
                               Object permission) {
        // 构建ABAC请求上下文
        AbacRequest request = new AbacRequest(
            authentication,
            targetDomainObject,
            permission.toString()
        );
        
        return policyEnforcement.check(request);
    }

    // 其他必要方法...
}

@Service
public class PolicyEnforcement {
    
    @Autowired
    private PolicyRepository policyRepository;
    
    public boolean check(AbacRequest request) {
        // 获取所有相关策略
        List<Policy> policies = policyRepository.findRelevantPolicies(
            request.getSubject(),
            request.getResource(),
            request.getAction()
        );
        
        // 评估策略
        return policies.stream().anyMatch(policy -> 
            evaluatePolicy(policy, request));
    }
    
    private boolean evaluatePolicy(Policy policy, AbacRequest request) {
        // 实现策略评估逻辑
        return true; // 简化示例
    }
}
3. 在控制器中使用
@RestController
@RequestMapping("/documents")
public class DocumentController {
    
    @PreAuthorize("hasPermission(#id, 'document', 'read')")
    @GetMapping("/{id}")
    public Document getDocument(@PathVariable Long id) {
        // ...
    }
    
    @PreAuthorize("hasPermission(#document, 'edit')")
    @PutMapping("/{id}")
    public Document updateDocument(@PathVariable Long id, 
                                 @RequestBody Document document) {
        // ...
    }
}

RBAC 与 ABAC 对比

特性RBACABAC
控制粒度粗粒度(基于角色)细粒度(基于属性)
灵活性较低
实现复杂度简单复杂
适用场景角色明确的系统需要复杂权限规则的系统
动态调整需要修改角色分配只需修改策略规则
性能相对较低(需评估复杂规则)

混合实现方案

在实际项目中,可以结合两种模型的优势:

@Service
public class HybridAccessService {
    
    @Autowired
    private RbacService rbacService;
    @Autowired
    private AbacService abacService;
    
    public boolean checkAccess(Authentication auth, 
                             HttpServletRequest request, 
                             Object domainObject) {
        // 先用RBAC做快速检查
        if (rbacService.hasRoleAccess(auth, "ADMIN")) {
            return true;
        }
        
        // 需要更细粒度控制时使用ABAC
        return abacService.checkAttributes(
            auth, 
            domainObject, 
            request.getMethod()
        );
    }
}

选择建议

  1. 选择 RBAC :

    • 权限结构相对简单固定

    • 角色数量有限且稳定

    • 不需要基于资源属性的访问控制

  2. 选择 ABAC :

    • 需要复杂的条件授权(时间、位置等)

    • 权限规则频繁变化

    • 需要基于资源属性的访问控制

    • 系统需要高度灵活的权限管理

Spring Security 原生更偏向 RBAC 模型,但通过自定义 PermissionEvaluator 和策略引擎可以实现 ABAC 功能。

Spring Security认证授权流程图概述

如何在 request 之间共享 SecurityContext?

既然SecurityContext 是存放在 ThreadLocal 中的,而且在每次权限鉴定的时候,都是从 ThreadLocal 中获取 SecurityContext 中保存的 Authentication。那么既然不同的 request 属于不同的线程,为什么每次都可以从 ThreadLocal 中获取到当前用户对应的 SecurityContext 呢?

  • 在 Web 应用中这是通过 SecurityContextPersistentFilter 实现的,默认情况下其在每次请求开始的时候,都会从 session 中获取 SecurityContext,然后把它设置给 SecurityContextHolder。
  • 在请求结束后又会将 SecurityContextHolder 所持有的 SecurityContext 保存在 session 中,并且清除 SecurityContextHolder 所持有的 SecurityContext。
  • 这样当我们第一次访问系统的时候,SecurityContextHolder 所持有的 SecurityContext 肯定是空的。待我们登录成功后,SecurityContextHolder 所持有的 SecurityContext 就不是空的了,且包含有认证成功的 Authentication 对象。
  • 待请求结束后我们就会将 SecurityContext 存在 session 中,等到下次请求的时候就可以从 session 中获取到该 SecurityContext 并把它赋予给 SecurityContextHolder 了。
  • 由于 SecurityContextHolder 已经持有认证过的 Authentication 对象了,所以下次访问的时候也就不再需要进行登录认证了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2406907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…

Visual Studio Code 扩展

Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后&#xff0c;命令 changeCase.commands 可预览转换效果 EmmyLua…

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践

前言&#xff1a;本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中&#xff0c;跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南&#xff0c;你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案&#xff0c;并结合内网…

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、基础概念 1. 哈希核心思想&#xff1a; 哈希函数的作用&#xff1a;通过此函数建立一个Key与存储位置之间的映射关系。理想目标&#xff1a;实现…

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展&#xff0c;尤其是大模型&#xff08;LLM&#xff09;在各行各业的深度应用和整合&#xff0c;企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者&#xff0c;还是积极拥抱AI转型的传统企业&#xff0c;在面向公众…

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…