SpringBoot 如何使用 ACL 进行访问控制

news2025/1/18 8:22:16

SpringBoot 如何使用 ACL 进行访问控制

在现代 Web 开发中,访问控制是一个非常重要的问题。访问控制可以帮助我们保护敏感信息、防止恶意攻击、维护系统安全等。Spring Security 是一个非常流行的安全框架,它提供了一系列的认证和授权功能,可以帮助我们实现灵活的访问控制。在本文中,我们将介绍如何使用 SpringBoot 和 Spring Security 中的 ACL(Access Control List)来实现访问控制。

在这里插入图片描述

什么是 ACL?

ACL(Access Control List)是一种常见的访问控制机制。ACL 可以控制用户对资源的访问权限。它是一种灵活、可扩展的访问控制机制,可以适应不同的应用场景。

ACL 通常由两个部分组成:访问主体和资源。访问主体可以是用户、角色、组织等,资源可以是文件、数据库表、API 接口等。ACL 可以定义哪些访问主体有权访问哪些资源,并可以设置不同的访问权限,例如读取、修改、删除等。

Spring Security 中的 ACL

Spring Security 是一个基于 Spring 的安全框架,它提供了一系列的认证和授权功能。Spring Security 中的 ACL 可以帮助我们实现灵活的访问控制,它提供了一些基本的 ACL 功能,例如:

  • 定义 ACL 权限
  • 创建和删除 ACL 权限
  • 将 ACL 权限与用户或角色关联
  • 检查用户或角色是否拥有某个 ACL 权限

在 Spring Security 中,ACL 是通过 AclService 和 AclRepository 接口来管理的。AclService 提供了一些基本的 ACL 操作,例如创建 ACL 权限、删除 ACL 权限等。AclRepository 提供了一些查询方法,可以查询 ACL 权限的相关信息。

使用 SpringBoot 和 Spring Security 实现 ACL 访问控制

接下来,我们将介绍如何使用 SpringBoot 和 Spring Security 实现 ACL 访问控制。

准备工作

首先,我们需要准备以下环境:

  • JDK 1.8 或以上版本
  • Maven 3.3 或以上版本
  • SpringBoot 2.5.2 或以上版本
  • MySQL 数据库

创建 SpringBoot 项目

我们可以使用 Spring Initializr 来快速创建一个 SpringBoot 项目。在创建项目时,我们需要添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-acl</artifactId>
    <version>5.5.1</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

这些依赖包含了 Spring Security 和 ACL 相关的组件和依赖。

配置数据库

我们需要配置数据库,以便 SpringBoot 和 Spring Security 可以使用 ACL 来管理访问控制。我们可以在 application.properties 文件中添加以下配置:

spring.datasource.url=jdbc:mysql://localhost:3306/acl_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

这些配置可以让 SpringBoot 自动创建数据库表,并将 ACL 相关的数据存储到数据库中。

创建 ACL 权限

接下来,我们需要创建 ACL 权限。ACL 权限包含以下信息:

  • ObjectIdentity:对象标识符,用于标识资源
  • Sid:安全标识符,用于标识访问主体
  • Permission:权限,用于标识访问权限

我们可以创建一个名为 AclPermission 的实体类,用于表示 ACL 权限:

@Entity
@Table(name = "acl_permission")
public class AclPermission implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "object_id_identity")
    private ObjectIdentity objectIdentity;

    @ManyToOne
    @JoinColumn(name = "sid")
    private Sid sid;

    @Column(name = "permission")
    private int permission;

    // getters and setters
}

在这个实体类中,我们定义了以下属性:

  • id:ACL 权限的唯一标识符
  • objectIdentity:对象标识符,用于标识资源
  • sid:安全标识符,用于标识访问主体
  • permission:权限,用于标识访问权限

创建 ACL 相关的服务

接下来,我们需要创建 ACL 相关的服务。我们可以创建一个名为 AclServiceImpl 的服务来实现 ACL 相关的操作:

@Service
public class AclServiceImpl implements AclService {

    private final AclRepository aclRepository;

    public AclServiceImpl(AclRepository aclRepository) {
        this.aclRepository = aclRepository;
    }

    @Override
    public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
        return aclRepository.findChildren(parentIdentity);
    }

    @Override
    public Acl readAclById(ObjectIdentity objectIdentity) throws NotFoundException {
        return aclRepository.findById(objectIdentity.getIdentifier())
                .orElseThrow(() -> new NotFoundException("ACL not found"));
    }

    @Override
    public Acl readAclByIdentifier(ObjectIdentity objectIdentity) throws NotFoundException {
        return aclRepository.findById(objectIdentity.getIdentifier())
                .orElseThrow(() -> new NotFoundException("ACL not found"));
    }

    @Override
    public Acl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
        if (aclRepository.existsById(objectIdentity.getIdentifier())) {
            throw new AlreadyExistsException("ACL already exists");
        }
        Acl acl = new AclImpl(objectIdentity, objectIdentity.getIdentifier(), null,
                true, new PrincipalSid("admin"), new Date());
        return aclRepository.save(acl);
    }

    @Override
    public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws NotFoundException {
        Optional<Acl> aclOptional = aclRepository.findById(objectIdentity.getIdentifier());
        if (aclOptional.isPresent()) {
            Acl acl = aclOptional.get();
            aclRepository.delete(acl);
        } else {
            throw new NotFoundException("ACL not found");
        }
    }

    @Override
    public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
        return aclRepository.save((AclImpl) acl);
    }

    @Override
    public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren, boolean deleteChildrenOnly) throws NotFoundException {
        throw new NotImplementedException();
    }
}

在这个服务中,我们实现了 AclService 接口中的方法,包括:

  • findChildren:查询子资源
  • readAclById:根据对象标识符查询 ACL
  • readAclByIdentifier:根据对象标识符查询 ACL
  • createAcl:创建 ACL
  • deleteAcl:删除 ACL
  • updateAcl:更新 ACL

配置 Spring Security

接下来,我们需要配置 Spring Security。我们可以创建一个名为 WebSecurityConfig 的类来配置 Spring Security:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private AclService aclService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").access("hasRole('ADMIN')")
                .antMatchers("/user/**").access("hasRole('USER')")
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
                .and().formLogin()
                .and().httpBasic()
                .and().csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }

    @Bean
    public JdbcMutableAclService jdbcMutableAclService() {
        return new JdbcMutableAclService(dataSource, new DefaultPermissionGrantingStrategy(), new ConsoleAuditLogger());
    }

    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(jdbcMutableAclService()));
        return expressionHandler;
    }

    @Bean
    public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(jdbcMutableAclService()));
        return expressionHandler;
    }

    @Bean
    public AclPermissionEvaluator aclPermissionEvaluator() {
        return new AclPermissionEvaluator(jdbcMutableAclService());
    }

    @Bean
    public ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy() {
        return new ObjectIdentityRetrievalStrategy();
    }

    @Bean
    public AclAuthorizationStrategy aclAuthorizationStrategy() {
        return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMIN"));
    }

    @Bean
    public PermissionGrantingStrategy permissionGrantingStrategy() {
        return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
    }

    @Bean
    public DefaultMethodSecurityMetadataSource methodSecurityMetadataSource() {
        DefaultMethodSecurityMetadataSource metadataSource = new DefaultMethodSecurityMetadataSource();
        metadataSource.setExpressionHandler(methodSecurityExpressionHandler());
        return metadataSource;
    }

    @Bean
    public DefaultWebSecurityMetadataSource webSecurityMetadataSource() {
        DefaultWebSecurityMetadataSource metadataSource = new DefaultWebSecurityMetadataSource();
        metadataSource.setExpressionHandler(webSecurityExpressionHandler());
        return metadataSource;
    }

    @Bean
    public AclSecurityInterceptor aclSecurityInterceptor() throws Exception {
        AclSecurityInterceptor interceptor = new AclSecurityInterceptor(jdbcMutableAclService(), objectIdentityRetrievalStrategy(), aclAuthorizationStrategy(), permissionGrantingStrategy());
        interceptor.setMethodSecurityMetadataSource(methodSecurityMetadataSource());
        interceptor.setSecurityMetadataSource(webSecurityMetadataSource());
        interceptor.setAuthenticationManager(authenticationManagerBean());
        return interceptor;
    }

    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

在这个配置类中,我们完成了以下工作:

  • 配置了访问控制规则,定义了哪些 URL 需要哪些角色才能访问
  • 配置了认证方式,使用了 JDBC 认证
  • 配置了 ACL 相关的组件,包括 MutableAclService、MethodSecurityExpressionHandler 等
  • 配置了 AclSecurityInterceptor,用于处理 ACL 相关的访问控制

创建控制器和视图

最后,我们需要创建控制器和视图来测试 ACL 访问控制。我们可以创建一个名为 DemoController 的控制器:

@RestController
public class DemoController {

    @GetMapping("/public/hello")
    public String hello() {
        return "Hello, public!";
    }

    @GetMapping("/user/hello")
    public String helloUser() {
        return "Hello, user!";
    }

    @GetMapping("/admin/hello")
    public String helloAdmin() {
        return "Hello, admin!";
    }
}

在这个控制器中,我们定义了三个接口,分别对应不同的访问权限。

接下来,我们可以创建相应的视图。我们可以在 resources/templates 目录下创建三个 HTML 文件,分别对应不同的接口:

  • public.html:公共接口
  • user.html:需要 USER 角色才能访问的接口
  • admin.html:需要 ADMIN 角色才能访问的接口

测试 ACL 访问控制

现在,我们可以启动应用程序,并访问三个接口:

  • /public/hello:可以直接访问,不需要权限
  • /user/hello:需要 USER 角色才能访问
  • /admin/hello:需要 ADMIN 角色才能访问

我们可以使用 curl 命令来测试访问控制:

$ curl http://localhost:8080/public/hello
Hello, public!

$ curl http://localhost:8080/user/hello
HTTP/1.1 403
Content-Length: 0

这段代码是一个使用 Spring Security 实现 ACL 访问控制的配置类。ACL(Access Control List)访问控制是一种基于资源的访问控制方式,可以控制用户对特定资源的访问权限。

具体来说,这个配置类完成了以下几个方面的工作:

  1. 配置了 HTTP 安全性,包括定义了哪些 URL 需要哪些角色才能访问。
  2. 配置了认证机制,使用 JDBC 认证。
  3. 配置了 ACL 相关的组件,包括 MutableAclService、MethodSecurityExpressionHandler 等。
  4. 配置了 AclSecurityInterceptor,用于实现 ACL 访问控制。

这个配置类的核心是 AclSecurityInterceptor,它是一个 Spring Security 的拦截器,用于在请求到达控制器之前检查用户是否有访问资源的权限。AclSecurityInterceptor 依赖于其他几个组件,包括 MutableAclService、MethodSecurityExpressionHandler 等,这些组件都是为了实现 ACL 访问控制而创建的。

总的来说,这个配置类的作用是实现 ACL 访问控制,确保用户只能访问他们有权限访问的资源。

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

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

相关文章

【网络1】协议及相关命令

文章目录 1.局域网&#xff1a;CSMA/CD2.互联网&#xff1a;ARP&#xff0c;DHCP&#xff0c;NAT3.TCP协议&#xff1a;telnet&#xff0c;tcpdump&#xff0c;syn/accept队列4.HTTPS协议&#xff1a;摘要&#xff08;sha、md5、crc&#xff09;。win对文件MD5校验&#xff1a;…

【博弈论笔记】第三章 完全且完美信息动态博弈

文章目录 第三章 完全且完美信息动态博弈3.1 动态博弈的表示法和特点3.2 策略的可信性和纳什均衡的不稳定问题3.2.1 相机选择和策略的可信性问题3.2.2 纳什均衡的不稳定问题3.2.3 逆推归纳法 3.3 子博弈和子博弈完美纳什均衡3.3.1 子博弈3.3.2 子博弈完美纳什均衡 3.4 四个经典…

规则引擎--函数式编程和and/or操作符的设计

目录 Java函数编程的一些基础知识BiFunctionBinaryOperatorstream reduce And, Or操作符and 逻辑 的 Combiner 如下:or 逻辑 的 Combiner 如下:and, or的执行 接上一篇博文&#xff1a;规则引擎–规则逻辑形如“1 & (2 | 3)“的抽象&#xff0c; 重点分析一下And, Or操作符…

反射(reflection)详细讲解

反射(reflection) 反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息&#xff08;比如成员变量&#xff0c;构造器&#xff0c;成员方法等等&#xff09;&#xff0c;并能操作对象的属性及方法。反射在设计模式和框架底层都会用到加载完类之后&#xff0c;在堆…

【博弈论笔记】第四章 重复博弈

文章目录 第四章 重复博弈4.1 重复博弈引论4.1.1 重复博弈定义和意义4.1.2 重复博弈的基本概念 4.2 有限次重复博弈4.2.1 两人零和博弈的有限次重复博弈4.2.2 唯一纯策略纳什均衡博弈的有限次重复博弈4.2.3 多个纯策略纳什均衡博弈的有限次重复博弈4.2.4 有限次重复博弈的民间定…

Python学习笔记(3)--字符串定义、拼接、格式化,表达式格式化,数据输入,布尔数据类型,比较运算符

传送门>B站黑马python入门教程 目录 1.字符串定义方式2.字符串拼接3.字符串格式化3.1 常用占位符3.2 格式化时的数字精度控制3.3 快速格式化字符串 4. 表达式格式化5. 数据输入-input语句6.布尔数据类型、比较运算符 1.字符串定义方式 在 python 语法中,字符串有三种定义方式…

Python爬虫 从小白到高手 Urllib

Urllib 1.什么是互联网爬虫&#xff1f; 如果我们把互联网比作一张大的蜘蛛网&#xff0c;那一台计算机上的数据便是蜘蛛网上的一个猎物&#xff0c;而爬虫程序就是一只小蜘蛛&#xff0c;沿着蜘蛛网抓取自己想要的数据 解释1&#xff1a;通过一个程序&#xff0c;根据Url(http…

行为型模式--访问者模式

目录 概述 结构 案例实现 优缺点 优点&#xff1a; 缺点&#xff1a; 使用场景 概述 封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变这个数据结构的前提下定义作用于这 些元素的新的操作。 结构 访问者模式包含以下主要角色: 抽象访问者&am…

采用SpringBoot+Tinymce实现文章的在线预览和上传

采用SpringBootTinymce实现文章的在线预览和上传 资源在gitee中 输入信息 预览

canvas详解09-像素操作

到目前为止,我们尚未深入了解 Canvas 画布真实像素的原理,事实上,你可以直接通过 ImageData 对象操纵像素数据,直接读取或将数据数组写入该对象中。稍后我们也将深入了解如何控制图像使其平滑(反锯齿)以及如何从 Canvas 画布中保存图像。 #ImageData 对象 ImageData对象…

el-table渲染二级对象数组

1、序言 项目地址如下&#xff1a;https://gitee.com/liu-wenxin/complexELTable.git 想要渲染这样的数据&#xff1a; el-table官网给的例子都是一级对象数组&#xff0c;如果想要渲染二级对象数组&#xff0c;直接 :table tableData 这样el-table渲染是不成功的&am…

RadEx Pro处理电火花数据操作步骤(下)

RadEx Pro处理电火花数据操作步骤&#xff08;上&#xff09;主要讲述RadEx Pro读取电火花数据&#xff0c;查看数据的质量&#xff0c;以及简单的滤波和振幅纠正。 6、海底拾取&#xff0c;建立流程060 seafloor pick Trace Input加载stack数据集 Trace Header Math&#x…

【人工智能】— 维度灾难、降维、主成分分析PCA、获取旧数据、非线性主成分分析

【人工智能】— 维度灾难、降维、主成分分析PCA、获取旧数据、非线性主成分分析 高维数据与维度灾难维度灾难降维为什么需要降维&#xff1f;PRINCIPLE COMPONENT ANALYSIS主成分的几何图像最小化到直线距离的平方和举例主成分的代数推导优化问题计算主成分&#xff08;Princip…

【Pandas】pandas用法解析(上)

目录 一、生成数据表 1.导入pandas库 2.导入CSV或者xlsx文件 3.用pandas创建数据表 二、数据表信息查看 1.维度查看 2.数据表基本信息&#xff08;维度、列名称、数据格式、所占空间等&#xff09; 3.每一列数据的格式 4.某一列格式 5.空值判断 6.查看某一列空值 7…

黑马程序员前端 Vue3 小兔鲜电商项目——(七)详情页

文章目录 路由配置模板代码配置路由链接跳转 渲染基础数据封装接口渲染数据 热榜区域模板代码封装接口渲染数据 图片预览组件封装小图切换大图显示模版代码绑定事件 放大镜效果图片优化 SKU组件熟悉全局组件统一插件化插件化开发插件注册 路由配置 模板代码 创建 src\views\D…

快速排序-详解附Python代码

排序思路 取一个元素P&#xff08;第一个元素&#xff09;&#xff0c;目标是使得元素P归位&#xff1b;列表被元素P分成了两个部分&#xff0c;左边的比P小&#xff0c;右边的比P大&#xff1b;分别再对左右两个部分的列表重复1&#xff0c;2步骤&#xff0c;递归完成排序 评…

7Z010 引脚功能详解

本文针对7Z010芯片&#xff0c;详细讲解硬件设计需要注意的技术点&#xff0c;可以作为设计和检查时候的参考文件。问了方便实用&#xff0c;按照Bank顺序排列&#xff0c;包含配置Bank、HR Bank、HP Bank、GTX Bank、供电引脚等。 参考文档包括&#xff1a; ds187-XC7Z010-X…

前端编写贪吃蛇游戏-附详细代码

当我们在前端编写贪吃蛇游戏时&#xff0c;可以按照以下步骤进行&#xff1a; 先看截图&#xff1a; 设置游戏板&#xff1a;创建一个HTML元素作为游戏板&#xff0c;可以使用<div>元素&#xff0c;并为其设置合适的样式。 绘制蛇和食物&#xff1a;使用JavaScript代码…

【Linux 基础入门 + Java项目部署】

文章目录 Linux 基础入门1 Linux 简介1.1不同应用领域的主流操作系统1.2 Linux发展历史与 Linux系统版本 2 Linux 安装2.1 安装方式介绍2.2 安装Linux2.3 网卡设置2.4 安装SSH连接工具 Linux和Windows目录结构对比3 Linux 常用命令3.1 Linux命令初体验3.2 文件目录操作命令lscd…

7A50T 引脚功能详解

本文针对7A50T芯片&#xff0c;详细讲解硬件设计需要注意的技术点&#xff0c;可以作为设计和检查时候的参考文件。问了方便实用&#xff0c;按照Bank顺序排列&#xff0c;包含配置Bank、HR Bank、HP Bank、GTP Bank、供电引脚等。 参考文档包括&#xff1a; ds181_Artix_7_D…