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

Security方法注解权限控制过程及自定义权限表达式

文章目录

    • 使用内置的权限表达式
      • @PreAuthorize
      • PermissionEvaluator
    • 自定义权限表达式
      • SysMethodSecurityExpressionHandler
        • 源码流程
      • SysMethodSecurityExpressionRoot

使用内置的权限表达式

@PreAuthorize

这个用来判断超级管理员的话,还得在表达式上加上

PermissionEvaluator

本来是想定义一个 PermissionEvaluator,但是发现,写表达式的时候,还得弄2个参数,@PreAuthorize(‘/admin/user/list’,‘user:list’),有点麻烦

package com.zzhua.blog.config.security.auth;import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;import java.io.Serializable;// GlobalMethodSecurityConfiguration 在 afterSingletonsInstantiated 方法中,// 会去容器中寻找 PermissionEvaluator 的bean, 设置到 defaultMethodExpressionHandler 中,// 并且定义了一个 PreInvocationAuthorizationAdvice 的bean, 将刚刚的设置到 defaultMethodExpressionHandler 设置给了这个Advice,//// GlobalMethodSecurityConfiguration 并且定义了aop中的 methodSecurityInterceptor(),会去创建访问决策管理器,// 访问决策管理器会去添加投票器,里面会创建一个 PreInvocationAuthorizationAdviceVoter, 里面会传入上面定义的Advice,//// 所以接下来的流程看这个拦截器就行了,同时,也离不开 MethodSecurityMetadataSourceAdvisor 切面的支持 因此,方法鉴权就是基于Aop的实现,// 用法参考:SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证-https://juejin.cn/post/6844903974546456590#heading-4
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {@Overridepublic boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {return false;}@Overridepublic boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {return false;}
}

自定义权限表达式

(也可以采用若依的方法,自定义权限表达式,其实就是利用了el表达式,但是通过自定义权限表达式的过程,可以更加清楚security处理方法注解权限时的整个处理过程,我们也可以在这里扩展一些权限通配符匹配的功能)

SysMethodSecurityExpressionHandler

可参考:如何在 Spring Security 中自定义权限表达式

源码流程

此handler 将会被注入到 GlobalMethodSecurityConfiguration#setMethodSecurityExpressionHandler 作为 handler

GlobalMethodSecurityConfiguration 定义了一个 PreInvocationAuthorizationAdvice 的bean, 获取并设置了上面定义的 handler

GlobalMethodSecurityConfiguration 并且定义了aop中的 methodSecurityInterceptor()拦截器,会去创建访问决策管理器

访问决策管理器会去添加投票器(当然,不止这一种投票器),会创建一个 PreInvocationAuthorizationAdviceVoter, 里面会传入上面定义的Advice,

@EnableWebSecurity引入了一个 MethodSecurityMetadataSourceAdvisorRegistrar ,
它创建了 MethodSecurityMetadataSourceAdvisor 切面, 并且指定了上面的拦截器名字作为构造参数, 使用 MethodSecurityMetadataSource 的实现(实现也有多种,通过组合的方式), 确定需要切入的bean(后面从方法中提取权限表达式,也是交给这个来实现)

所以后面的流程就是:

  • 当一个请求来到切入的方法,就会被拦截器处理, MethodSecurityInterceptor 拦截器 会拿到 AOP里面的 MethodInvocation,
  • 然后它会根据方法中的注解, 提取出所需权限, 交给访问决策管理器, 访问决策管理器 再交给 投票器,
  • 因此, 上面创建的投票器 又会交给 advice, advice又交给handler处理, 也就是下面定义的这个handler处理,
  • handler再利用el表达式计算, el会需要一个rootObject, 具体方法可以定义在rootObject里面, 只需要返回布尔值即可
package com.zzhua.blog.config.security.auth;import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;/*可参考:如何在 Spring Security 中自定义权限表达式-https://juejin.cn/post/7119086250610409508此handler 将会被注入到 GlobalMethodSecurityConfiguration#setMethodSecurityExpressionHandler 作为 handlerGlobalMethodSecurityConfiguration 定义了一个 PreInvocationAuthorizationAdvice 的bean, 获取并设置了上面定义的 handlerGlobalMethodSecurityConfiguration 并且定义了aop中的 methodSecurityInterceptor()拦截器,会去创建访问决策管理器访问决策管理器会去添加投票器(当然,不止这一种投票器),会创建一个 PreInvocationAuthorizationAdviceVoter, 里面会传入上面定义的Advice,@EnableWebSecurity引入了一个 MethodSecurityMetadataSourceAdvisorRegistrar ,它创建了 MethodSecurityMetadataSourceAdvisor 切面, 并且指定了上面的拦截器名字作为构造参数,使用 MethodSecurityMetadataSource 的实现(实现也有多种,通过组合的方式), 确定需要切入的bean(后面从方法中提取权限表达式,也是交给这个来实现)所以后面的流程就是:当一个请求来到切入的方法,就会被拦截器处理, MethodSecurityInterceptor 拦截器 会拿到 AOP里面的 MethodInvocation,然后它会根据方法中的注解, 提取出所需权限, 交给访问决策管理器, 访问决策管理器 再交给 投票器,因此, 上面创建的投票器 又会交给 advice, advice又交给handler处理, 也就是下面定义的这个handler处理,handler再利用el表达式计算, el会需要一个rootObject, 具体方法可以定义在rootObject里面, 只需要返回布尔值即可
*/
@Component
public class SysMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {@Overrideprotected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,MethodInvocation invocation) {// 换成自己的实现,其它的都照抄源码里面的(下面又多了可以很多自定义的东西了)SysMethodSecurityExpressionRoot root = new SysMethodSecurityExpressionRoot(authentication);root.setThis(invocation.getThis());root.setPermissionEvaluator(getPermissionEvaluator());root.setTrustResolver(new AuthenticationTrustResolverImpl());root.setRoleHierarchy(getRoleHierarchy());// root.setDefaultRolePrefix("ROLE_");return root;}}

SysMethodSecurityExpressionRoot

package com.zzhua.blog.config.security.auth;import com.zzhua.blog.config.constant.SysConstants;
import com.zzhua.blog.config.security.UserDetailDTO;
import com.zzhua.blog.util.SecurityUtil;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;class SysMethodSecurityExpressionRootextends SecurityExpressionRootimplements MethodSecurityExpressionOperations {private Object filterObject;private Object returnObject;private Object target;SysMethodSecurityExpressionRoot(Authentication a) {super(a);}/* 自定义鉴权方法 */public boolean isAuth(String permission) {UserDetailDTO userDetailDTO = SecurityUtil.getPrincipal();if (SysConstants.IS_ADMIN.equals(userDetailDTO.getIsAdmin())) {return true;} else {List<String> authories = getAuthories();for (String authory : authories) {if (Objects.equals(authory, permission)) {return true;}}}return false;}private List<String> getAuthories() {Collection<? extends GrantedAuthority> authorities = getAuthentication().getAuthorities();List<String> authoritys = authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());return authoritys;}public void setFilterObject(Object filterObject) {this.filterObject = filterObject;}public Object getFilterObject() {return filterObject;}public void setReturnObject(Object returnObject) {this.returnObject = returnObject;}public Object getReturnObject() {return returnObject;}void setThis(Object target) {this.target = target;}public Object getThis() {return target;}
}

相关文章:

Security方法注解权限控制过程及自定义权限表达式

文章目录 使用内置的权限表达式PreAuthorizePermissionEvaluator 自定义权限表达式SysMethodSecurityExpressionHandler源码流程 SysMethodSecurityExpressionRoot 使用内置的权限表达式 PreAuthorize 这个用来判断超级管理员的话&#xff0c;还得在表达式上加上或 Permissi…...

vue 省市县三级联动

1、 <template><div>所在省<el-select popper-class"eloption" :popper-append-to-body"true"change"getShiList(obj.province)" v-model"obj.province" placeholder"请选择所在省" clearableclear"re…...

ChatGPT实现编程语言转换

编程语言转换 对于程序员来说&#xff0c;往往有一类工作&#xff0c;是需要将一部分业务逻辑实现从服务端转移到客户端&#xff0c;或者从客户端转移到服务端。这类工作&#xff0c;通常需要将一种编程语言的代码转换成另一种编程语言的代码&#xff0c;这就需要承担这项工作…...

浅拷贝和深拷贝

浅拷贝&#xff1a; 定义&#xff1a;浅拷贝&#xff08;Shallow Copy&#xff09;是一种简单的对象复制方式&#xff0c;将一个对象的数据成员直接复制给另一个对象&#xff08;通常是通过默认的复制构造函数或赋值运算符实现&#xff09;&#xff0c;这些数据成员可以是基本…...

进程地址空间与页表方面知识点(缺页中断及写时拷贝部分原理)

谢谢阅读&#xff0c;如有错误请大佬留言&#xff01;&#xff01; 目录 谢谢阅读&#xff0c;如有错误请大佬留言&#xff01;&#xff01; 抛出总结 开始介绍 发现问题 进程地址空间&#xff08;虚拟地址&#xff09; 页表 物理内存与进程地址空间映射 缺页中断基本…...

Photoshop如何使用滤镜之实例演示?

文章目录 0.引言1.将普通照片制作成油画效果2.使用液化滤镜修出完美身材3.用镜头光晕滤镜制作唯美的逆光人像4.用Camera Raw滤镜对偏色风景照进行调色 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及其…...

Flutter 组件抽取:日期(DatePicker)、时间(TimePicker)弹窗选择器【仿照】

简介 仿照《Flutter 仿ios自定义一个DatePicker》实行的日期弹窗选择器&#xff08;DatePicker&#xff09;、时间弹窗选择器&#xff08;TimePicker&#xff09; 效果 范例 class _TestPageState extends State<TestPage> {overridevoid initState() {super.initStat…...

基于opencv的YOLOV3对图片的目标检测

目录 1. 准备工作 2. utils 函数 2.1 plot_show 函数 2.2 get_prediction 函数 2.3 draw_bounding_box 绘制边界框函数...

Mermaid流程图

所有流程图都由节点&#xff0c;几何形状和边缘&#xff0c;箭头或线条组成。mermaid代码定义了这些节点和边缘的制作和交互方式。 它还可以容纳不同的箭头类型、多方向箭头以及与子图之间的链接。 1、流程图的方向 TB - 从上到下TD - 自上而下/与上到下相同BT - 从下到上RL -…...

国产!全志科技T507-H工业核心板( 4核ARM Cortex-A5)规格书

1核心板简介 创龙科技 SOM-TLT507 是一款基于全志科技 T507-H 处理器设计的 4 核 ARM Cortex-A 53 全国产工业核心板,主频高达 1.416GHz 。核心板 CPU 、ROM 、RAM、电源、晶振等所有元器件均采用国产工业级方案,国产化率 100%。 核心板通过邮票孔连接方式引出 MIPI CSI 、…...

java小记 2023-05-05

public class Test {/*** 谓类的方法就是指类中用static 修饰的方法&#xff08;非static 为实例方法&#xff09;&#xff0c;比如main 方法&#xff0c;那么可以以main* 方法为例&#xff0c;可直接调用其他类方法&#xff0c;必须通过实例调用实例方法&#xff0c;this 关键…...

CentOS安装Nginx

准备工作 在安装Nginx之前&#xff0c;我们需要进行一些准备工作&#xff1a; 确认系统是否已经安装了Nginx。如果已经安装了&#xff0c;需要卸载掉旧版本。安装EPEL源&#xff0c;以获取Nginx的软件包。安装必要的依赖软件包。 卸载旧版Nginx 如果已经安装了旧版本的Ngin…...

CSS布局基础(CSS书写顺序 导航栏写法 常见问题)

CSS布局基础&#xff08;CSS书写顺序 & 导航栏写法&#xff09; CSS布局基础&#xff08;CSS书写顺序&#xff09;导航栏写法PC端网页开发一般步骤容易出问题的点 CSS布局基础&#xff08;CSS书写顺序&#xff09; 布局定位属性自身属性&#xff08;宽高&#xff0c;边框&…...

打造卓越 QML 层级设计:从入门到精通

目录标题 引言&#xff1a;QML 层级设计的重要性1.1 什么是 QML1.2 层级设计的核心理念1.3 实际应用案例 QML 基础知识2.1 语言概述2.2 基本元素2.3 属性和信号 设计原则与规范3.1 命名规范3.1.1 标识符命名3.1.2 文件命名3.1.3 文件夹命名 3.2 代码风格3.2.1 缩进与空格3.2.2 …...

shell流程控制之条件判断练习

1、判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查一次磁盘剩余空间。​ 因为如果磁盘剩余空间小于20G需要报警发送邮件给管理员&#xff0c;所以需要对管理员的邮箱进行设置 &#xff08;1&#xff09;首先…...

linux中TF启动卡制作:磁盘分区文件同步

文章目录 前言&#xff1a;1. 连接TF卡2. 磁盘卸载载与分区2.1 磁盘卸载2.2 创建第一个分区2.3 创建第二个分区 3. 磁盘格式化4. 文件同步5. 检查与BOOT分区启动文件拷贝总结&#xff1a; 前言&#xff1a; TF卡在linux环境下配置好相关软件后&#xff0c;把配置好的系统以及软…...

【操作系统OS】学习笔记:第一章 操作系统基础【哈工大李治军老师】

基于本人观看学习 哈工大李治军老师主讲的操作系统课程 所做的笔记&#xff0c;仅进行交流分享。 特此鸣谢李治军老师&#xff0c;操作系统的神作&#xff01; 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0…...

Linux C/C++ 网络编程中地址格式转换(inet_pton和inet_ntop函数)

网络编程中地址格式转换&#xff08;inet_pton和inet_ntop函数&#xff09; 地址格式转换 #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h>int inet_pton(int af , const char * src ,void * dst);&#xff08;1&#xf…...

庖丁解牛函数知识---C语言《2》

目录 前言&#xff1a; 1.嵌套调用函数 2.链式访问 3.函数的声明与定义 4.*递归 5.递归与非递归 ❤博主CSDN:啊苏要学习 ▶专栏分类&#xff1a;C语言◀ C语言的学习&#xff0c;是为我们今后学习其它语言打好基础&#xff0c;C生万物&#xff01; 开始我们的C语言之旅吧…...

Git 使用教程:最详细、最正宗手把手教学(万字长文)

目录 一&#xff1a;Git二&#xff1a;SVN与Git的的区别三、安装Git四&#xff1a;常规操作五&#xff1a;远程仓库六&#xff1a;创建与合并分支七&#xff1a;bug分支八&#xff1a;多人协作九&#xff1a;git可视化工具 Git Git 是一种分布式版本控制系统&#xff0c;用于…...

CTFshow F5杯 逆向与隐写实战解析 超详细

1. CTFshow F5杯逆向与隐写技术全景解析 去年参加F5杯时&#xff0c;我对着那道LSB隐写题折腾到凌晨三点。当终于从图片噪点中提取出flag那一刻&#xff0c;突然理解了什么叫做"数字世界的考古学"。逆向工程和隐写术就像侦探破案&#xff0c;需要同时具备技术功底和发…...

鸿蒙一气总论(四)

第四卷 文明溯源四域同源 华夏主脉定宗 卷首引 天地既定&#xff0c;人神分途&#xff0c;万物安立&#xff0c;四海生民逐水土而居。 四方之地&#xff0c;山川不同、水土异质、气运有别&#xff0c; 然归根溯源&#xff0c;同承鸿蒙一气&#xff0c;共禀混元道体。 四大…...

PacketStreamer传感器工作原理:深入解析BPF过滤机制

PacketStreamer传感器工作原理&#xff1a;深入解析BPF过滤机制 【免费下载链接】PacketStreamer :star: :star: Distributed tcpdump for cloud native environments :star: :star: 项目地址: https://gitcode.com/gh_mirrors/pa/PacketStreamer PacketStreamer是一款专…...

3步实现智能自动化:三月七小助手如何每天为你节省90分钟游戏时间?

3步实现智能自动化&#xff1a;三月七小助手如何每天为你节省90分钟游戏时间&#xff1f; 【免费下载链接】March7thAssistant 崩坏&#xff1a;星穹铁道全自动 三月七小助手 项目地址: https://gitcode.com/gh_mirrors/ma/March7thAssistant 你是否每天花费大量时间在《…...

芯片功能验证的范式革新:从约束随机到目标驱动的智能场景生成

1. 功能验证的十字路口&#xff1a;我们为何陷入困境&#xff1f;在芯片设计这个行当里摸爬滚打了十几年&#xff0c;我亲眼见证了功能验证从一个相对简单的环节&#xff0c;演变成如今整个设计流程中最耗时、最昂贵、也最令人头疼的瓶颈。这感觉就像你精心设计了一辆跑车&…...

TTS推理优化:低精度计算与硬件协同设计实践

1. 项目概述&#xff1a;TTS推理的经济学重构在语音技术领域&#xff0c;文本转语音&#xff08;TTS&#xff09;系统正从实验室走向生产环境&#xff0c;成为智能助手、无障碍工具和实时通信系统的核心组件。与大型语言模型&#xff08;LLM&#xff09;不同&#xff0c;TTS需要…...

蓝牙技术与FPGA实现:原理、优化与实践

1. 蓝牙技术基础与核心原理蓝牙技术自1994年由爱立信首次提出以来&#xff0c;已成为短距离无线通信领域的事实标准。这项技术之所以能在众多无线方案中脱颖而出&#xff0c;关键在于其独特的物理层设计和灵活的协议架构。1.1 2.4GHz ISM频段特性蓝牙工作在2.4GHz工业、科学和医…...

双模型工作流架构解析:从原理到实践,构建高效AI应用

1. 项目概述&#xff1a;双模型工作流的魅力与挑战最近在GitHub上看到一个挺有意思的项目&#xff0c;叫cait52099/openclaw-dual-model-workflow。光看名字&#xff0c;openclaw&#xff08;开放之爪&#xff09;和dual-model-workflow&#xff08;双模型工作流&#xff09;这…...

AIAgent服务降级总失效?用SITS2026定义的3类语义韧性指标重构你的容错策略

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AIAgent服务降级失效的根源诊断 AIAgent 服务在高并发或依赖组件异常时&#xff0c;常配置熔断与降级策略&#xff0c;但实践中频繁出现降级逻辑未触发、兜底响应缺失或返回错误码而非预设友好内容等问…...

Acorn Archimedes 上的 PipeDream:打破软件常规,却也带来使用挑战的生产力套件

历史背景在家庭计算机发展的“百花齐放、适者生存”阶段&#xff0c;直到 1995 年左右&#xff0c;众多产品纷纷涌现&#xff0c;但很多都未能站稳脚跟。Acorn Computer Ltd. 在著名的 8 位 BBC Micro 之后推出了 Archimedes。1983 年&#xff0c;Acorn 启动了 Acorn RISC Mach…...