当前位置: 首页 > news >正文

后端进阶之路——浅谈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 {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("{noop}password") // 使用 "{noop}" 前缀表示密码不加密.roles("USER");}@Overrideprotected 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 {@Autowiredprivate DataSource dataSource;@Overrideprotected 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=?");}@Overrideprotected 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 {@Autowiredprivate DataSource dataSource;@Overrideprotected 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=?");}@Overrideprotected 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 {@Autowiredprivate DataSource dataSource;@Overrideprotected 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=?");}@Overrideprotected 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;@Autowiredpublic 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 {@Overrideprotected 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 {@Overrideprotected 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();}@Beanpublic DefaultWebSecurityExpressionHandler expressionHandler() {DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();expressionHandler.setRoleHierarchy(roleHierarchy());return expressionHandler;}@Beanpublic 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风格的路径匹配规则或表达式语言编写更复杂的访问规则,以限制用户对特定路径或功能的访问权限。
通过定义这些元素,可以确保系统的安全性和可靠性。

在这里插入图片描述

相关文章:

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

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ 解决算法&#xff0c;一个专栏就够了★ ★ 架…...

Mac 安装不在 Apple 商店授权的应用程序

文章目录 一、场景介绍二、实操说明 一、场景介绍 在日常的工作生活中&#xff0c;发现一些好用的应用程序&#xff0c;但是出于某些原因&#xff0c;应用程序的开发者并没有将安装包上架到苹果商店。 那么这些优秀的应用程序下载安装以后就会出现如下弹框被拒之门外 二、实操…...

【MyBatis】MyBatis把空字符串转换成0的问题处理方案(96)

先看问题: Postman入参: MyBatis采用map循环插入: // Mapper接口层void addPar(Param(value "question") Map<String, Object> paramMap);<!-- 新增&#xff1a;参数 --><insert id"addPar" parameterType"map">INSERT IGNO…...

OpenLayers实战,OpenLayers获取移动端精确定位,OpenLayers适配App混合H5方式调用手机定位位置并定位到指定点

专栏目录: OpenLayers实战进阶专栏目录 前言 本章讲解OpenLayers如何获取移动端精确定位位置。不使用任何native本地方法,只使用纯js实现。 本篇文章适用于App混合H5方式调用手机精确定位,打包时需要选择GPS位置权限,手机获取定位过程中会弹出是否允许定位的权限提示。 …...

Go指针取址问题:循环后每次都拿到相同内容

例子&#xff1a; func main() {yourList : [...]int{1, 2, 3}yourMap1 : make(map[int]*int)yourMap2 : make(map[int]*int)for key, value : range yourList {// 修改前yourMap1[key] &value// 修改后tmp : valueyourMap2[key] &tmpfmt.Println(value, &value…...

用Rust实现23种设计模式之简单工厂

在 Rust 中&#xff0c;可以使用结构体和 trait 来实现工厂方法模式。工厂方法模式是一种创建型设计模式&#xff0c;通过定义一个创建对象的接口&#xff0c;让子类决定实例化哪个类。下面是一个简单的示例&#xff0c;展示了如何使用 Rust 实现工厂方法模式&#xff1a; // …...

SpringBoot + minio实现分片上传、秒传、续传

什么是minio MinIO是一个基于Go实现的高性能、兼容S3协议的对象存储。它采用GNU AGPL v3开源协议&#xff0c;项目地址是https://github.com/minio/minio。 引用官网&#xff1a; MinIO是根据GNU Affero通用公共许可证v3.0发布的高性能对象存储。它与Amazon S3云存储服务兼容…...

logback 里面设置 自动删除3天之前的日志

目录 1 实现 1 实现 要实现达到一定大小后将日志文件压缩&#xff0c;并删除三天前的日志数据&#xff0c;可以结合使用 SizeAndTimeBasedRollingPolicy 滚动策略和 DeleteOlderThan 选项来配置。下面是一个示例配置&#xff0c;实现日志文件达到一定大小后进行滚动和压缩&…...

对于数据库查询索引和查字典索引的理解

之前面试问过我对于数据库索引的理解&#xff0c;这个问题不是具体的问题太宽泛&#xff0c;面试官也没进行引导&#xff0c;我不知道怎么回答&#xff0c;下面是结合查字典进行理解。 查字典 拿查字典举例&#xff0c;知道一个字怎么写但是不知道具体的意思以及发音&#xff…...

git删除已经提交的大文件

当你不小心把一个巨大的二进制文件提交到git仓库的时候&#xff0c;此时删除再提交也没有用了&#xff0c;大文件已经在仓库中留底了。另外比如需要删除某个需要保密的文件&#xff0c;都是相同的解决办法。 我本来想着把dll放在三方库里面提交到仓库里&#xff0c;省得在不同…...

【数据分析】pandas 一

目录 一&#xff0c;pandas简介&#xff1a; 二&#xff0c;pandas数据结构Series简介&#xff1a; 2.1 data为ndarray 2.2 data为字典 三&#xff0c;Serise切片操作&#xff1a; 四&#xff0c;Series性质&#xff1a; 4.1 Series类似于numpy,字典 4.2 矢量化操作和标…...

题解 | #G.Gcd# 2023牛客暑期多校6

G.Gcd 数论 题目大意 给定一个包含两个非负数的初始集合 S { x , y } S\{x,y\} S{x,y} 每次操作可以选定其中不相等的两个数 a , b a,b a,b &#xff0c;并将 a − b a-b a−b 或 g c d ( a , b ) gcd(a,b) gcd(a,b) 置入集合 S S S &#xff0c;其中 g c d ( 0 , a …...

苍穹外卖day10——订单状态定时处理(Spring Task)、来单提醒和客户催单(WebSocket)

预期效果 对于超时没处理的需要定时程序处理。基于SpringTask实现。 来单提醒和客户催单。基于WebSocket实现。 Spring Task 介绍 Cron表达式 周几通常不能和日一起指定。 cron表达式在线生成器 在线Cron表达式生成器 入门案例 创建定时任务类 /*** 定义定时任务类*/ Slf4j…...

【多线程初阶】多线程案例之单例模式

文章目录 前言1. 什么是单例模式2. 饿汉模式3. 懒汉模式 --- 单线程版4. 懒汉模式 --- 多线程版5. 懒汉模式 --- 多线程改进版总结 前言 本文主要给大家讲解多线程的一个重要案例 — 单例模式. 关注收藏, 开始学习吧&#x1f9d0; 1. 什么是单例模式 单例模式是一种很经典的…...

跨境选品怎么选?建议独立站卖家收下这份利基产品查找攻略!

跨境电商平台现在可谓是火热发展中&#xff0c;独立站出海风口&#xff0c;其实选择的机会还真不少&#xff0c;相比国内电商的发展势头&#xff0c;看得出来&#xff0c;未来跨境电商的大门&#xff0c;对你而言&#xff0c;敞开着。选品这事儿&#xff0c;就像你上战场前挑选…...

[C++项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍...

项目背景 Boost库是C中一个非常重要的开源库. 它实现了许多C标准库中没有涉及的特性和功能, 一度成为了C标准库的拓展库. C新标准的内容, 很大一部分脱胎于Boost库中. Boost库的高质量代码 以及 提供了更多实用方便的C组件, 使得Boost库在C开发中会被高频使用 为方便开发者学…...

opencv-32 图像平滑处理-高斯滤波cv2.GaussianBlur()

在进行均值滤波和方框滤波时&#xff0c;其邻域内每个像素的权重是相等的。在高斯滤波中&#xff0c;会将中心点的权重值加大&#xff0c;远离中心点的权重值减小&#xff0c;在此基础上计算邻域内各个像素值不同权重 的和。 基本原理 在高斯滤波中&#xff0c;卷积核中的值不…...

Windows 环境Kubernetes安装

目录 前言 安装 Docker 安装 Kubernetes Windows 安装 kubectl 介绍 安装 开启 Kubernetes 前言 Docker作为当前最流行的容器化平台&#xff0c;为Kubernetes提供了强大的容器化技术基础。Kubernetes与Docker的结合&#xff0c;使得容器化应用程序在大规模集群中得以简…...

自建类ChatGPT服务:本地化部署与远程访问教程

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

常用SQL语句总结

SQL语句 文章目录 SQL语句1 SQL语句简介2 DQL&#xff08;数据查询语句&#xff09;3 DML&#xff08;数据操纵语句&#xff09;4 DDL&#xff08;数据定义语句&#xff09;5 DCL&#xff08;数据控制语句&#xff09;6 TCL&#xff08;事务控制语句&#xff09; 1 SQL语句简介…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...