若依权限校验源码分析

news2024/11/15 19:48:49

若依的权限校验实现原理就是AOP+自定义注解,代码并不多,debug跟一遍之后很容易理解,详细流程整理如下

用到的类

  • 注解类RequiresLogin、RequiresPermissions、RequiresRoles,分别用于登录认证、权限认证和角色认证
  • 切面类PreAuthorizeAspect,基于 Spring Aop 的注解鉴权
  • 被代理类SysJobController,被代理类就是添加注解的方法所在的类,可以是任意一个类

链路跟踪

在需要鉴权的方法上添加对应的注解
@RequiresPermissions(“monitor:job:list”)表示需要在该方法执行前进行权限认证,参数即具体权限

/**
* 查询定时任务列表
*/
@RequiresPermissions("monitor:job:list")
@GetMapping("/list")
public TableDataInfo list(SysJob sysJob) {
	startPage();
	List<SysJob> list = jobService.selectJobList(sysJob);
	return getDataTable(list);
}

执行切面类

package com.zhy.common.security.aspect;

import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.zhy.common.security.annotation.RequiresLogin;
import com.zhy.common.security.annotation.RequiresPermissions;
import com.zhy.common.security.annotation.RequiresRoles;
import com.zhy.common.security.auth.AuthUtil;

/**
 * 基于 Spring Aop 的注解鉴权
 *
 * @author kong
 */
@Aspect
@Component
public class PreAuthorizeAspect
{
    /**
     * 构建
     */
    public PreAuthorizeAspect()
    {
    }

    /**
     * 定义AOP签名 (切入所有使用鉴权注解的方法)
     */
    public static final String POINTCUT_SIGN = " @annotation(com.zhy.common.security.annotation.RequiresLogin) || "
            + "@annotation(com.zhy.common.security.annotation.RequiresPermissions) || "
            + "@annotation(com.zhy.common.security.annotation.RequiresRoles)";

    /**
     * 声明AOP签名
     */
    @Pointcut(POINTCUT_SIGN)
    public void pointcut()
    {
    }

    /**
     * 环绕切入
     *
     * @param joinPoint 切面对象
     * @return 底层方法执行后的返回值
     * @throws Throwable 底层方法抛出的异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable
    {
        // 注解鉴权
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        checkMethodAnnotation(signature.getMethod());
        try
        {
            // 执行原有逻辑
            Object obj = joinPoint.proceed();
            return obj;
        }
        catch (Throwable e)
        {
            throw e;
        }
    }

    /**
     * 对一个Method对象进行注解检查
     */
    public void checkMethodAnnotation(Method method)
    {
        // 校验 @RequiresLogin 注解
        RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);
        if (requiresLogin != null)
        {
            AuthUtil.checkLogin();
        }

        // 校验 @RequiresRoles 注解
        RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
        if (requiresRoles != null)
        {
            AuthUtil.checkRole(requiresRoles);
        }

        // 校验 @RequiresPermissions 注解
        RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
        if (requiresPermissions != null)
        {
            AuthUtil.checkPermi(requiresPermissions);
        }
    }
}

debug进到around方法
signature.getMethod()获取到添加注解的方法

在这里插入图片描述

进到checkMethodAnnotation方法
拿到注解所在方法后首先判断该方法上添加了哪些注解,可以有一个或多个,此处只添加了@RequiresPermissions注解

在这里插入图片描述

进入校验权限认证的方法
权限验证工具类跟进到权限验证逻辑实现类

在这里插入图片描述

首先是调用SecurityContextHolder.setPermission
在这里插入图片描述

debug进入set方法
在这里插入图片描述

这里ROLE_PERMISSION是在SecurityConstants即权限相关通用常量类中定义的,该类中的其他属性如DETAILS_USER_ID、DETAILS_USERNAME、USER_KEY、LOGIN_USER等都是在用户登录时进行赋值

进入set方法,这里的getLocalMap最终获取的是TransmittableThreadLocal类型的THREAD_LOCAL集合,该集合中也存放了上面说的SecurityConstants类中的其他属性。TransmittableThreadLocal相比ThreadLocal而言优点在于能够处理处理父子线程变量不能共用的情况,ThreadLocal是跟当前线程挂钩的,所以脱离当前线程它就起不了作用

在这里插入图片描述

回到checkPermi方法中,这里判断为true,因为@RequiresPermissions注解中的logical默认值就是Logical.AND枚举字段,Logical枚举类有两个属性,AND和OR,表示验证用户所有的权限还是部分权限,继续执行checkPermiAnd方法

在这里插入图片描述

checkPermiAnd方法进来后首先获取当前账号的权限列表,debug进去

在这里插入图片描述

可以看到这里获取到admin账号的权限是"* : * : *",这个值也是登录流程中进行赋值

在这里插入图片描述

现在账号权限有了,执行业务逻辑需要的权限也有了,接下来就是进行比对了,如果通过那么AOP的任务就完成了,可以继续执行业务逻辑,不通过的会会抛出异常

在这里插入图片描述

debug进入hasPermi方法,来看看是怎么进行比对的,这里传进来的两个参数authorities和permission就是需要比对的值,值分别为"* : * : *“和"monitor:job:list”,可以看到这里用到了java8Stream中提供的filter过滤器,StringUtils::hasText过滤条件使用了双冒号运算符,表示遍历authorities集合中的元素作为参数调用 StringUtils工具类中的 hasText方法。anyMatch()表示进行匹配,其中x表示authorities权限列表中的元素,ALL_PERMISSION.contains(x)表示在 ALL_PERMISSION字符串中是否存在字符串x,PatternMatchUtils.simpleMatch(x, permission)) 表示 permission 中是否存在与 x 相匹配的子字符串。这里用到了或运算,由于ALL_PERMISSION是个字符串,值就是"* : * : *",所以ALL_PERMISSION.contains(x)永远为true,此处会发生或运算短路,意味着PatternMatchUtils.simpleMatch(x, permission)) 不会执行,所以return true

在这里插入图片描述

到此整个权限验证逻辑执行完毕

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

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

相关文章

极米H5评测:极米H5投影仪参数如何?极米H5值得入手吗?

作为家用智能投影领域的佼佼者&#xff0c;极米在上个月结束的双11活动中&#xff0c;实现了全网成交总额破8亿&#xff0c;并获得天猫、京东和抖音投影品类销量和GMV双第一的成绩&#xff0c;同时这也是极米连续第九次成为投影品类冠军。能够实现如此优秀的成绩&#xff0c;也…

JS逆向之webpack 通用扣取思路

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!标题 环境 win10chrome106目标站:aHR0cHM6Ly93d3cuZ205OS5jb20v 加密参数 password: K6YEmQrNy%2FQgdnac…

安卓玩机搞机技巧综合资源------EROFS分区格式 小米红米机型分区类型 刷写recovery方法列举【三】

接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your device is corrupt. 设备内部报错 AB分区等等【二】 &#x1f49d;&#x1f49d;&#x1f49d;&#x1f49d…

高性能数据访问中间件 OBProxy(七):安全、协议和监控

经过本系列前六篇文章的分布式特性介绍&#xff0c;相信大家已经了解了 OBProxy 在 OceanBase 数据库整体架构下的作用。本篇文章我们将换一个视角&#xff0c;介绍一些偏“中间件”的功能&#xff1a;安全、协议和监控功能。 从 OBProxy 整体来看&#xff0c;安全、协议和监控…

Scratch少儿编程英语教程

Scratch少儿编程英语教程 在 Scratch 中学习编程、创建游戏、玩得开心&#xff01;致未来编码员的家长和老师 课程英文名&#xff1a;Programming for Kids and Beginners Learn to Code in Scratch 此视频教程共5.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印…

网上图书商城小程序毕业设计,微信图书商城小程序系统设计与实现,微信小程序毕业设计论文怎么写毕设源码开题报告需求分析怎么做

功能清单 【后台管理员功能】 会员列表&#xff1a;查看所有注册会员信息&#xff0c;支持删除 录入资讯&#xff1a;录入资讯标题、内容等信息 管理资讯&#xff1a;查看已录入资讯列表&#xff0c;支持删除和修改 广告设置&#xff1a;上传图片和设置小程序首页轮播图广告地…

QT(3)-QTableView

QTableView1 说明2 常用函数2.1 clearSpans2.2 setSpan2.3 columnAt2.4 rowAt2.5 columnSpan2.6 rowSpan2.7 columnViewportPosition2.8 rowViewportPosition2.9 列宽、行高2.9.1 columnWidth2.9.2 rowHeight2.9.3 setColumnWidth2.9.4 setRowHeight2.9.5 resizeColumnToConten…

gitlab结合semantic-release自动化发布npm插件(二)

前言 在内部组织架构开发npm包时&#xff0c;很多人会想到规范问题&#xff0c;难道按前文gitlab结合semantic-release自动化规范git流程(一)所描述根据git的CI/CD就可以了吗&#xff0c;每次发布都会版本对应的新增&#xff0c;而往往新增的版本不是我们所需要的&#xff0c;…

如何去掉视频上的水印文字?视频去水印方法大分享

我们在网上看到喜欢的视频&#xff0c;都会保存下来&#xff0c;经常能够看到保存下来的这些视频中都带有水印。这些带有水印的视频在后期的观看过程中&#xff0c;会很影响整个画面&#xff0c;所以我们在保存下来后&#xff0c;可以选择将视频中的水印去除。那么视频如何去水…

物料管理系统最基本的功能有哪些?

随着企业信息化的快速发展&#xff0c;传统企业的企业快速增长与管理水平、手段滞后之间的矛盾已成为影响企业发展的重要因素和阻碍企业战略目标实现的主要矛盾。尤其是对于一些传统的中小型制造企业企业而言&#xff0c;以往的信息化系统所做的相应规划已经完全不能适用于高速…

【论文阅读32】《Texture Defragmentation for Photo-Reconstructed 3D Models》

目录 1 introduction 2 overview 3 Related work 3.1 Single-patch Mesh Parametrization 3.2 Global Mesh Parametrization 3.3 Signal-Specialized UV Maps 3.4 Mesh repairing 3.5 Alleviating the effect of seams 3.6 Packing of texture charts 4 Phases of the algorith…

初阶数据结构学习记录——열넷 排序(3)

归并排序 归并的思路其实和二叉树&#xff0c;快排都有点像。归并希望左、右半区间有序。和快排不同&#xff0c;先分裂后排序&#xff0c;一半一半分&#xff0c;分到最后每个区间只剩一个1个数字&#xff0c;这个区间一定是有序的&#xff0c;因为只有一个数字&#xff0c;往…

kubernetes的基本使用

文章目录kubernetes的基本使用1、部署方式1、部署方式的演进图2、各部署方式的特点2、架构的简单说明1、架构简图2、各组件说明1、控制平面组件&#xff08;Control Plane Components&#xff09;1、kube-apiserver2、etcd3、kube-scheduler4、kube-controller-manager5、cloud…

Apache HTTPD 换行解析漏洞

漏洞介绍&#xff1a; Apache HTTPD是一款HTTP服务器&#xff0c;它可以通过mod_php来运行PHP网页。 影响版本&#xff1a;Apache 2.4.0~2.4.29 存在一个解析漏洞&#xff1b;在解析PHP时&#xff0c;1.php\x0A将被按照PHP后缀进行解析&#xff0c;导致绕过一些服务器的安全策…

Windows中cmd命令窗口一些有用的小技巧命令

使用小功能记录 命令功能help显示所有dos命令&#xff0c;help >> cmd.txt,会把命令输出成文档altprtscreen快速截取命令行窗口esc清除当前命令行tab补全路径&#xff0c;若知道路径开头可快速补全&#xff0c;包含隐藏文件&#xff0c;但文件夹多又不知道路径开始字符时…

scrapy框架了解与使用

scrapy介绍与安装 Scrapy 是开源和协作的一个基于 Twisted 实现的异步处理爬虫框架使用纯 Python 语言编写&#xff0c;被誉为爬虫界的Django&#xff0c;Scrapy 框架应用广泛&#xff0c;常用于数据采集、网络监测&#xff0c;以及自动化测试等 Scrapy安装 mac、linux系统 …

【入门AI】利用Paddle实现简单的数字识别

梳理逻辑 整个流程 准备好Paddle的环境准备好训练样本设计模型(定义模型)训练模型模型测试 1、准备好环境 #加载飞桨和相关类库 import paddle from paddle.nn import Linear import paddle.nn.functional as F import os import numpy as np import matplotlib.pyplot as plt…

集美大学第14届蓝桥校选题解

本次比赛的出题表如下&#xff1a; 退役一年&#xff0c;勋总还是那么强呜呜呜 目录填空题[1] 十甚至九题意思路拓展[蓝桥杯] XXX 进制减法第十三届蓝桥杯C/C省赛B组 E题[2] 九大于十题意思路[3] N皇后签到题[1] JMU最强蓝人[2] 哪有赌狗一直输[3] 元胞自动机题意思路代码实…

PLC程序实例二:ModBusTCP客户端编程实例与测试方法

一、需求描述 1、设备作为服务端时&#xff0c;需要给出对应的测试方法&#xff0c;即要求 PLC 作为客户端&#xff0c;设备作为服务端&#xff0c;因此要求编写 PLC 的ModBusTCP客户端 2、先了解一下设备作为服务端的ModBusTCP网络触发业务逻辑 &#xff08;1&#xff09;设…

SQL 语法速成手册

基本概念 数据库术语 数据库&#xff08;database&#xff09;&#xff1a;保存有组织的数据的容器&#xff08;通常是一个文件或一组文件&#xff09;。数据表&#xff08;table&#xff09; &#xff1a;某种特定类型数据的结构化清单。模式&#xff08;schema&#xff09;…