后端进阶之路——浅谈Spring Security用户、角色、权限和访问规则(三)

前言

在这里插入图片描述
「作者主页」:雪碧有白泡泡
「个人网站」:雪碧的个人网站
「推荐专栏」

java一站式服务
前端炫酷代码分享
uniapp-从构建到提升
从0到英雄,vue成神之路
解决算法,一个专栏就够了
架构咱们从0说
★ 数据流通的精妙之道★

★后端进阶之路★

请添加图片描述

在这里插入图片描述

文章目录

  • 前言
  • 引言
  • 1. 定义用户
    • 使用内存方式定义用户
    • 使用数据库方式定义用户
  • 2. 定义角色
    • 创建角色并将其与用户关联
    • 解释如何使用角色来组织和控制权限
  • 3. 定义权限
  • 4. 访问规则
      • 使用Ant风格的路径匹配规则
      • 使用表达式语言进行更复杂的访问规则定义
  • 小结

引言

继上篇后端进阶之路——深入理解Spring Security配置(二)
在这里插入图片描述

1. 定义用户

使用内存方式定义用户

在内存中定义用户是一种简单的方法,适用于开发和测试环境。我们可以在Spring Security的配置类中使用InMemoryUserDetailsManager来定义用户。下面是一个示例:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password") // 使用 "{noop}" 前缀表示密码不加密
                .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
}

上述示例中,使用withUser方法定义了一个用户名为"user",密码为"password",角色为"USER"的用户。注意,密码的前缀"{noop}"表示密码不加密,这只适用于开发和测试环境。

使用数据库方式定义用户

在实际生产环境中,通常会将用户信息存储在数据库中。使用数据库方式定义用户需要进行以下步骤:

  1. 创建数据库表格来存储用户信息,例如表格名为"users",包含列"username"、“password"和"role”。
  2. 配置Spring Security以连接到数据库,并使用数据库中的用户信息进行认证和授权。

下面是一个使用数据库方式定义用户的示例:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username=?")
                .authoritiesByUsernameQuery("SELECT username, role FROM users WHERE username=?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
}

上述示例中,通过dataSource注入了数据源,然后使用jdbcAuthentication配置了基于数据库的认证和授权。.usersByUsernameQuery()方法指定了查询用户名、密码和启用状态的SQL语句,.authoritiesByUsernameQuery()方法指定了查询用户名和角色的SQL语句。

2. 定义角色

在Spring Security中,可以使用角色来组织和控制权限。角色是一组权限的集合,可以通过将角色与用户关联来授予用户相应的权限。

以下是在Spring Security中定义角色并将其与用户关联的示例代码:

创建角色并将其与用户关联

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username=?")
                .authoritiesByUsernameQuery("SELECT username, role FROM users WHERE username=?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN") // 需要"ADMIN"角色才能访问"/admin/**"路径
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
}

在上述示例中,.antMatchers("/admin/**").hasRole("ADMIN")指定了只有拥有"ADMIN"角色的用户才能访问"/admin/**"路径。这样,我们可以根据不同的角色来限制用户对某些资源的访问权限。

解释如何使用角色来组织和控制权限

在Spring Security中,可以使用角色来定义访问控制规则,并使用这些规则来保护应用程序的不同部分。通过为用户分配不同的角色,可以实现对不同用户的权限控制。

以下是一个使用角色进行权限控制的示例代码:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username=?")
                .authoritiesByUsernameQuery("SELECT username, role FROM users WHERE username=?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN") // 需要"ADMIN"角色才能访问"/admin/**"路径
                .antMatchers("/user/**").hasRole("USER") // 需要"USER"角色才能访问"/user/**"路径
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
}

上述示例中,使用.antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER")定义了不同路径需要不同角色的访问权限。只有拥有相应角色的用户才能访问对应的路径。

3. 定义权限

权限是指在系统中对特定资源或操作进行访问控制的能力。它是用于确保只有经过授权的用户或角色才能执行某些敏感操作或访问某些受限资源的机制。权限的定义和管理对于确保系统的安全性和保护重要数据非常重要。

在Spring Security中,我们可以使用@PreAuthorize@PostAuthorize@Secured等注解来定义权限。这些注解可以放置在方法上,用于限制只有具有特定权限的用户才能调用该方法。

下面是一个示例,演示了如何在Spring Security中定义权限:

首先,确保你已经添加了Spring Security的依赖到你的项目中。

<!-- pom.xml -->
<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    ...
</dependencies>

接下来,创建一个自定义的权限验证类。

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;

@Component
public class MyAuthorization {

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void adminOnly() {
        // 只有具有ROLE_ADMIN角色的用户才能调用此方法
    }

    @PreAuthorize("hasAuthority('WRITE_PERMISSION')")
    public void writeAccess() {
        // 只有具有WRITE_PERMISSION权限的用户才能调用此方法
    }

}

在上述代码中,MyAuthorization类包含了两个方法:adminOnly()writeAccess()。这两个方法都使用了@PreAuthorize注解来定义权限。

hasRole('ROLE_ADMIN')表示只有具有ROLE_ADMIN角色的用户才能调用adminOnly()方法。

hasAuthority('WRITE_PERMISSION')表示只有具有WRITE_PERMISSION权限的用户才能调用writeAccess()方法。

然后,在你的业务逻辑中,可以通过依赖注入的方式使用MyAuthorization类,并调用相应的方法。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    private final MyAuthorization myAuthorization;

    @Autowired
    public MyService(MyAuthorization myAuthorization) {
        this.myAuthorization = myAuthorization;
    }

    public void doSomething() {
        myAuthorization.adminOnly(); // 调用需要admin权限的方法
        myAuthorization.writeAccess(); // 调用需要writeAccess权限的方法
    }

}

在上述代码中,MyService类依赖注入了MyAuthorization类,并在doSomething()方法中调用了其中的两个方法。

4. 访问规则

当使用Spring Security进行访问控制时,可以通过Ant风格的路径匹配规则和表达式语言来定义更复杂的访问规则。下面是一些示例代码片段,用于说明如何使用这些规则:

使用Ant风格的路径匹配规则

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic();
    }
}

在上述代码中,我们使用authorizeRequests()方法来配置路径的访问规则。.antMatchers()方法用于指定要匹配的路径模式,并使用hasRole()hasAnyRole()方法指定需要具有的角色。在这个例子中,如果请求的路径以"/admin/"开头,则用户需要具有"ADMIN"角色。

使用表达式语言进行更复杂的访问规则定义

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .expressionHandler(expressionHandler())
            .antMatchers("/admin/**").access("hasRole('ADMIN') or hasIpAddress('127.0.0.1')")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic();
    }

    @Bean
    public DefaultWebSecurityExpressionHandler expressionHandler() {
        DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
        expressionHandler.setRoleHierarchy(roleHierarchy());
        return expressionHandler;
    }

    @Bean
    public RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        return roleHierarchy;
    }
}

在上述代码中,我们使用.access()方法来定义更复杂的访问规则。这里我们使用表达式语言,可以通过hasRole()hasIpAddress()等方法来判断用户是否有权限访问路径。在这个例子中,如果请求的路径以"/admin/“开头,并且用户具有"ADMIN"角色或者IP地址为"127.0.0.1”,则允许访问。

另外,我们还使用DefaultWebSecurityExpressionHandlerRoleHierarchyImpl来配置角色层次关系。在这个例子中,"ROLE_ADMIN"角色被认为是"ROLE_USER"角色的父角色,因此具有"ROLE_ADMIN"角色的用户也将被授予"ROLE_USER"角色的权限。

小结

通过定义用户、角色、权限和访问规则
可以在SpringSecurity中实现灵活的访问控制和权限管理。可以使用内存方式或数据库方式定义用户,设置用户名、密码和角色等信息。角色可以用来组织和控制权限,可以将一组权限赋予特定角色,并将角色分配给用户。权限是指用户可以执行的特定操作或访问的资源,可以细化到每个功能或数据级别。可以使用Ant风格的路径匹配规则或表达式语言编写更复杂的访问规则,以限制用户对特定路径或功能的访问权限。
通过定义这些元素,可以确保系统的安全性和可靠性。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

概率论与数理统计复习总结3

概率论与数理统计复习总结&#xff0c;仅供笔者复习使用&#xff0c;参考教材&#xff1a; 《概率论与数理统计》/ 荣腾中主编. — 第 2 版. 高等教育出版社《2024高途考研数学——概率基础精讲》王喆 概率论与数理统计实际上是两个互补的分支&#xff1a;概率论 在 已知随机…

go编译文件

1.编译go文件 go build [go文件]2.执行文件编译文件 ./demo [demo为go文件名称]

SpringBoot使用redis作为缓存的实例

目录 什么是缓存&#xff1f; 缓存的作用&#xff1f; 缓存的成本&#xff1f; 实际项目中的应用 代码展示 什么是缓存&#xff1f; 缓存就是数据交换的缓冲区&#xff08;称作Cache [ kʃ ] &#xff09;&#xff0c;是存贮数据的临时地方&#xff0c;一般读写性能较高。 缓…

观察者模式(Observer)

观察着模式是一种行为设计模式&#xff0c;可以用来定义对象间的一对多依赖关系&#xff0c;使得每当一个对象状态发生改变时&#xff0c;其相关依赖对象皆得到通知并被自动更新。 观察者模式又叫做发布-订阅&#xff08;Publish/Subscribe&#xff09;模式、模型-视图&#xf…

《Java-SE-第二十三章》之单例模式

文章目录 单例模式概述饿汉模式懒汉模式单线程版懒汉单例多线程版枚举实现单例 单例模式概述 单例模式是设计模式中的一种,其作用能保证某个类在程序中只存在唯一一份实例,而不会创建多份实例。单例模式具体的实现方式, 分成 “饿汉” 和 “懒汉” 两种.。饿汉模式中的饿不并不…

2023年华数杯数学建模A题思路代码分析 - 隔热材料的结构优化控制研究

# 1 赛题 A 题 隔热材料的结构优化控制研究 新型隔热材料 A 具有优良的隔热特性&#xff0c;在航天、军工、石化、建筑、交通等 高科技领域中有着广泛的应用。 目前&#xff0c;由单根隔热材料 A 纤维编织成的织物&#xff0c;其热导率可以直接测出&#xff1b;但是 单根隔热…

【基于HBase和ElasticSearch构建大数据实时检索项目】

基于HBase和ElasticSearch构建大数据实时检索项目 一、项目说明二、环境搭建三、编写程序四、测试流程 一、项目说明 利用HBase存储海量数据&#xff0c;解决海量数据存储和实时更新查询的问题&#xff1b;利用ElasticSearch作为HBase索引&#xff0c;加快大数据集中实时查询数…

⌈C++⌋从无到有了解并掌握C++面向对象三大特性——封装、继承、多态

前置知识&#xff1a;类和对象 参考书籍&#xff1a;《C Primer 第五版》 目录 什么是面向过程&#xff1f;什么是面向对象&#xff1f; 一、封装 1、封装的含义以及如何实现封装 1.1 访问限定符&#xff08;访问说明符&#xff09; 1.2 什么是封装&#xff1f; 2、封装的优点…

css word-break

上面的一行还是可以放置很多个字符的&#xff0c;但是就是换行了。 要求填充满整行&#xff0c;超过在换行 加上word-break:break-all;就行

uniapp返回

// 监听返回事件onNavigationBarButtonTap() {uni.showModal({title: 提示,content: 确定要返回吗&#xff1f;,success: (res) > {if (res.confirm) {uni.navigateBack({delta: 2})}}})},

牛客网Verilog刷题——VL46

牛客网Verilog刷题——VL46 题目解析答案 题目 根据题目提供的双口RAM代码和接口描述&#xff0c;实现同步FIFO&#xff0c;要求FIFO位宽和深度参数化可配置。电路的接口如下图所示。   双口RAM端口说明&#xff1a; 同步FIFO端口说明&#xff1a; 双口RAM代码如下&#xff…

【LangChain】向量存储(Vector stores)

LangChain学习文档 【LangChain】向量存储(Vector stores)【LangChain】向量存储之FAISS 概要 存储和搜索非结构化数据的最常见方法之一是嵌入它并存储生成的嵌入向量&#xff0c;然后在查询时嵌入非结构化查询并检索与嵌入查询“最相似”的嵌入向量。向量存储负责存储嵌入数…

【Jmeter】配置不同业务请求比例,应对综合场景压测

目录 前言 Jmeter5.0新特性 核心改进 其他变化 资料获取方法 前言 Jmeter 5.0这次的核心改进是在许多地方改进了对 Rest 的支持&#xff0c;此外还有调试功能、录制功能的增强、报告的改进等。 我也是因为迁移到了Mac&#xff0c;准备在Mac上安装Jmeter的时候发现它已经…

机器学习---概述(一)

文章目录 1.人工智能、机器学习、深度学习2.机器学习的工作流程2.1 获取数据集2.2 数据基本处理2.3 特征工程2.3.1 特征提取2.3.2 特征预处理2.3.3 特征降维 2.4 机器学习2.5 模型评估 3.机器学习的算法分类3.1 监督学习3.1.1 回归问题3.1.2 分类问题 3.2 无监督学习3.3 半监督…

Scikit Learn识别手写数字 -- 机器学习项目基础篇(6)

Scikit learn是机器学习社区中使用最广泛的机器学习库之一&#xff0c;其背后的原因是代码的易用性和机器学习开发人员构建机器学习模型所需的几乎所有功能的可用性。在本文中&#xff0c;我们将学习如何使用sklearn在手写数字数据集上训练MLP模型。 其优势是&#xff1a; 它提…

Springboot 多数据源 dynamic-datasource动态添加移除数据源

0.前言 上一篇文章我们讲了如何通过多数据源组件&#xff0c;在Spring boot Druid 连接池项目中配置多数据源&#xff0c;并且通过DS注解的方式切换数据源&#xff0c;《Spring Boot 配置多数据源【最简单的方式】》。但是在多租户的业务场景中&#xff0c;我们通常需要手动的…

【方法】Excel表格如何拆分数据?

当需要把多个数据逐个填到Excel单元格的时候&#xff0c;我们可以利用Excel的数据拆分功能&#xff0c;可以节省不少时间。 小编以下面的数据为例&#xff0c;看看如何进行数据拆分。 首先&#xff0c;要选择数字所在的单元格&#xff0c;然后依次点击菜单栏中的“数据”>…

FFmpeg解码详细流程

介绍 FFmpeg的 libavcodec 模块完成音视频多媒体的编解码模块。老版本的 FFmpeg 将avcodec_decode_video2()作为视频的解码函数 API&#xff0c;将avcodec_decode_audio4()作为音频的解码函数 API&#xff1b;从 3.4版本开始已经将二者标记为废弃过时 API&#xff08;attribut…

Dockerfile构建lamp镜像

1、构建目录 [rootdocker ~]# mkdir compose_lamp [rootdocker ~]# cd compose_lamp/ 2、编写Docekerfile [rootdocker compose_lamp]# vim Dockerfile #基础镜像 FROM centos:7#维护该镜像的用户信息 MAINTAINER Crushlinux <crushlinux163.com>#安装httpd RUN yum -…

反转链表的两种方法

反转链表的两种方法 题目介绍 题目链接 206. 反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 效果图如下所示 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]解法一&#xff1a;迭代方法 解题思路&#xf…