后端进阶之路——浅谈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}"表示密码不加密,这只适用于开发和测试环境。
使用数据库方式定义用户
在实际生产环境中,通常会将用户信息存储在数据库中。使用数据库方式定义用户需要进行以下步骤:
- 创建数据库表格来存储用户信息,例如表格名为"users",包含列"username"、“password"和"role”。
- 配置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”,则允许访问。
另外,我们还使用DefaultWebSecurityExpressionHandler
和RoleHierarchyImpl
来配置角色层次关系。在这个例子中,"ROLE_ADMIN"角色被认为是"ROLE_USER"角色的父角色,因此具有"ROLE_ADMIN"角色的用户也将被授予"ROLE_USER"角色的权限。
小结
通过定义用户、角色、权限和访问规则
可以在SpringSecurity中实现灵活的访问控制和权限管理。可以使用内存方式或数据库方式定义用户,设置用户名、密码和角色等信息。角色可以用来组织和控制权限,可以将一组权限赋予特定角色,并将角色分配给用户。权限是指用户可以执行的特定操作或访问的资源,可以细化到每个功能或数据级别。可以使用Ant风格的路径匹配规则或表达式语言编写更复杂的访问规则,以限制用户对特定路径或功能的访问权限。
通过定义这些元素,可以确保系统的安全性和可靠性。
相关文章:

后端进阶之路——浅谈Spring Security用户、角色、权限和访问规则(三)
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄,vue成神之路★ ★ 解决算法,一个专栏就够了★ ★ 架…...

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

【MyBatis】MyBatis把空字符串转换成0的问题处理方案(96)
先看问题: Postman入参: MyBatis采用map循环插入: // Mapper接口层void addPar(Param(value "question") Map<String, Object> paramMap);<!-- 新增:参数 --><insert id"addPar" parameterType"map">INSERT IGNO…...

OpenLayers实战,OpenLayers获取移动端精确定位,OpenLayers适配App混合H5方式调用手机定位位置并定位到指定点
专栏目录: OpenLayers实战进阶专栏目录 前言 本章讲解OpenLayers如何获取移动端精确定位位置。不使用任何native本地方法,只使用纯js实现。 本篇文章适用于App混合H5方式调用手机精确定位,打包时需要选择GPS位置权限,手机获取定位过程中会弹出是否允许定位的权限提示。 …...
Go指针取址问题:循环后每次都拿到相同内容
例子: 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 中,可以使用结构体和 trait 来实现工厂方法模式。工厂方法模式是一种创建型设计模式,通过定义一个创建对象的接口,让子类决定实例化哪个类。下面是一个简单的示例,展示了如何使用 Rust 实现工厂方法模式: // …...

SpringBoot + minio实现分片上传、秒传、续传
什么是minio MinIO是一个基于Go实现的高性能、兼容S3协议的对象存储。它采用GNU AGPL v3开源协议,项目地址是https://github.com/minio/minio。 引用官网: MinIO是根据GNU Affero通用公共许可证v3.0发布的高性能对象存储。它与Amazon S3云存储服务兼容…...
logback 里面设置 自动删除3天之前的日志
目录 1 实现 1 实现 要实现达到一定大小后将日志文件压缩,并删除三天前的日志数据,可以结合使用 SizeAndTimeBasedRollingPolicy 滚动策略和 DeleteOlderThan 选项来配置。下面是一个示例配置,实现日志文件达到一定大小后进行滚动和压缩&…...

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

git删除已经提交的大文件
当你不小心把一个巨大的二进制文件提交到git仓库的时候,此时删除再提交也没有用了,大文件已经在仓库中留底了。另外比如需要删除某个需要保密的文件,都是相同的解决办法。 我本来想着把dll放在三方库里面提交到仓库里,省得在不同…...
【数据分析】pandas 一
目录 一,pandas简介: 二,pandas数据结构Series简介: 2.1 data为ndarray 2.2 data为字典 三,Serise切片操作: 四,Series性质: 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 ,并将 a − b a-b a−b 或 g c d ( a , b ) gcd(a,b) gcd(a,b) 置入集合 S S S ,其中 g c d ( 0 , a …...

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

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

跨境选品怎么选?建议独立站卖家收下这份利基产品查找攻略!
跨境电商平台现在可谓是火热发展中,独立站出海风口,其实选择的机会还真不少,相比国内电商的发展势头,看得出来,未来跨境电商的大门,对你而言,敞开着。选品这事儿,就像你上战场前挑选…...

[C++项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍...
项目背景 Boost库是C中一个非常重要的开源库. 它实现了许多C标准库中没有涉及的特性和功能, 一度成为了C标准库的拓展库. C新标准的内容, 很大一部分脱胎于Boost库中. Boost库的高质量代码 以及 提供了更多实用方便的C组件, 使得Boost库在C开发中会被高频使用 为方便开发者学…...

opencv-32 图像平滑处理-高斯滤波cv2.GaussianBlur()
在进行均值滤波和方框滤波时,其邻域内每个像素的权重是相等的。在高斯滤波中,会将中心点的权重值加大,远离中心点的权重值减小,在此基础上计算邻域内各个像素值不同权重 的和。 基本原理 在高斯滤波中,卷积核中的值不…...

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

自建类ChatGPT服务:本地化部署与远程访问教程
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...

常用SQL语句总结
SQL语句 文章目录 SQL语句1 SQL语句简介2 DQL(数据查询语句)3 DML(数据操纵语句)4 DDL(数据定义语句)5 DCL(数据控制语句)6 TCL(事务控制语句) 1 SQL语句简介…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...