当前位置: 首页 > 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;用于…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...