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

news2024/9/30 9:33:34

前言

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

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风格的路径匹配规则或表达式语言编写更复杂的访问规则,以限制用户对特定路径或功能的访问权限。
通过定义这些元素,可以确保系统的安全性和可靠性。

在这里插入图片描述

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

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

相关文章

Cocos creator(2d) 使用 shader + uv 实现单张图片衔接滚动效果

在游戏中&#xff0c;当我们需要让背景图片无缝衔接无限滚动时(打飞机这种背景一直滚动&#xff0c;或者肉鸽游戏地图一直在走等等)&#xff0c;通常的做法是 在游戏中放两个背景node&#xff0c;在update中控制这两张背景图片的移动&#xff0c;并让其收尾衔接即可。(具体代码…

2023-08-04 LeetCode每日一题(不同路径 III)

2023-08-04每日一题 一、题目编号 980. 不同路径 III二、题目链接 点击跳转到题目位置 三、题目描述 在二维网格 grid 上&#xff0c;有 4 种类型的方格&#xff1a; 1 表示起始方格。且只有一个起始方格。2 表示结束方格&#xff0c;且只有一个结束方格。0 表示我们可以…

自然语言处理: 第六章Transformer- 现代大模型的基石

理论基础 Transformer&#xff08;来自2017年google发表的Attention Is All You Need (arxiv.org) &#xff09;&#xff0c;接上面一篇attention之后&#xff0c;transformer是基于自注意力基础上引申出来的结构&#xff0c;其主要解决了seq2seq的两个问题: 考虑了原序列和目…

项目经理必读:领导风格对项目成功的关键影响

引言 项目经理作为一个领导者的角色&#xff0c;他们需要协调各方资源&#xff0c;管理团队&#xff0c;推动项目的进行。为了完成这些任务&#xff0c;项目经理必须具备各种领导风格的灵活性&#xff0c;以应对项目中的各种变数和挑战。在这篇文章中&#xff0c;我们将讨论领…

【洛谷】p1825 [USACO11OPEN] Corn Maze S

从快吃中饭开始看题&#xff0c;一直到晚上七点半终于AC了&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 写篇题解记录一下这个激动人心的时刻 文章目录 题目&#xff1a;[USACO11OPEN] Corn Maze S题面翻…

SpringMVC请求和响应

目录 1、简介 2、数据响应方式 2.1、页面跳转 2.1.1、直接返回字符串 2.1.2、ModelAndView 2.1.3、request域 2.2、回写数据 2.2.1、直接返回字符串 2.2.2、返回对象或集合 3、获得请求数据 3.1、基本类型参数 3.2、获得POJO类型参数 3.3、获得数组类型参数 3.4、…

【嵌入式学习笔记】嵌入式入门5——窗口看门狗WWDG

1.WWDG简介 WWDG的全称&#xff1a;Window watchdog&#xff0c;即窗口看门狗WWDG的本质&#xff1a;能产生系统复位信号和提前唤醒中断的计数器WWDG的特性&#xff1a;递减的计数器&#xff0c;当递减计数器值从 0x40减到0x3F时复位&#xff08;即T6位跳变到0&#xff09;&am…

代码随想录—力扣算法题:27移除元素.Java版(示例代码与导图详解)

版本说明 当前版本号[20230804]。 版本修改说明20230804初版 目录 文章目录 版本说明目录27. 移除元素思路暴力解法双指针法两个方法的区别总结双指针法要点 27. 移除元素 力扣题目链接 更多内容可点击此处跳转到代码随想录&#xff0c;看原版文件 给你一个数组 nums 和一…

VBA技术资料MF39:VBA_计算单元格中的字符数

【分享成果&#xff0c;随喜正能量】依赖也好&#xff0c;不依赖也罢&#xff0c;人的心灵都是需要安放的&#xff0c;有人安放在另一个人身上&#xff0c;有人安放在喜欢的事业之上&#xff0c;有人安放在宗教信仰之上&#xff0c;过程不同&#xff0c;终点都一样&#xff0c;…

C/C++实现librosa音频处理库melspectrogram和mfcc

C/C实现librosa音频处理库melspectrogram和mfcc 目录 C/C实现librosa音频处理库melspectrogram和mfcc 1.项目结构 2.依赖环境 3.C librosa音频处理库实现 (1) 对齐读取音频文件 (2) 对齐melspectrogram (3) 对齐MFCC 4.Demo运行 5.librosa库C源码下载 深度学习语音处…

人工智能学习1——特征提取和距离

强人工智能和弱人工智能&#xff1a; 强人工智能&#xff1a;和人脑一样 弱人工智能&#xff1a;不一定和人脑思考方式一样&#xff0c;但是可以达到相同的效果&#xff0c;弱人工智能并不弱 —————————————————————————————————— 机器学习能…

嘉楠勘智k230开发板上手记录(二)

上次成功在k230上烧录sdk&#xff0c;这次准备实现hello world和ssh scp远程k230 一、PC连接k230 1. 初步准备 首先下载串口工具PuTTY&#xff0c;这个我个人感觉比较方便。 准备两根USB type-C数据线&#xff0c;一根连电源&#xff0c;一根连串口调试。还有Type C公头转网…

【C#学习笔记】内存管理

文章目录 分配内存释放内存GC标记清除算法分代算法 .NET的GC机制有这样两个问题&#xff1a; 官方文档 自动内存管理 自动内存管理是CLR在托管执行过程中提供的服务之一。 公共语言运行时的垃圾回收器为应用程序管理内存的分配和释放。 对开发人员而言&#xff0c;这就意味着…

Ubuntu 虚拟机和主机无法互相复制文字和文件

1.在虚拟机列表中&#xff0c;右键查看是否有安装VMware Tools&#xff0c;如果没有安装点击安装&#xff0c;如果已经安装了&#xff0c;上面显示重现安装VMware Tools&#xff0c;并且为灰色&#xff0c;如图&#xff1a; 2.如果没有安装点击安装&#xff0c;如果已经安装&am…

【数据结构】堆的原理实现

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ 数据结构与算法       &#x1f6f0;️社区 :✈️ 进步学堂       &am…

C语言的浮点类型:float,double,long double

文章目录 浮点型概述浮点型常量浮点型常量的后缀 溢出上溢 overflow下溢 underflow 一个特殊的浮点值&#xff1a;NaN初始化 浮点型概述 float 称为单精度浮点型。 double 称为双精度浮点型。 long double 称为长双精度浮点型。 C 标准规定&#xff0c;float 必须至少精确到…

MySQL存储过程(二十四)

你相信吗&#xff0c; 相信那一天的夕阳吗? 上一章简单介绍了 MySQL的索引(二十三),如果没有看过,请观看上一章 一. 存储过程 MySQL从5.0版本开始支持存储过程和函数。存储过程和函数能够将复杂的SQL逻辑封装在一起&#xff0c; 应用程序无须关注存储过程和函数内部复杂的S…

【DBeaver】CLIENT_PLUGIN_AUTH is required

1、右键打开编辑连接弹窗&#xff0c;进入编辑驱动设置 2、选择“库” 3、全部删掉&#xff0c;然后点击“重置为默认状态” 4、选中然后点击“下载更新” 5、点击版本号&#xff0c;选择与mysql相同的版本 6、最后一步

使用可视化docker浏览器,轻松实现分布式web自动化

01、前言 顺着docker的发展&#xff0c;很多测试的同学也已经在测试工作上使用docker作为环境基础去进行一些自动化测试&#xff0c;这篇文章主要讲述我们在docker中使用浏览器进行自动化测试如果可以实现可视化&#xff0c;同时可以对浏览器进行相关的操作。 02、开篇 首先…

leetcode 33.搜索旋转排序数组

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;搜索旋转排序数组 ps&#xff1a; 本题是二分查找的变形&#xff0c;旋转排序数组之后其实会形成两个有序的区间。算出平均下标先判断是否与 target 相等&#xff0c;因为这样可以减少代码的冗余。如果前者不成立则使用平…