通过Aop实现限制修改删除指定账号的数据

购物车逻辑实现 Cookie缓存+Redis缓存 购物车实现逻辑: 购物车实现的功能: 1、将商品添加到购物车中 2、改变购物车商品数量 3、显示购物车的信息 将商品添加到购物车中功能分析如下: 1. 接收到商品ID 2. 根据商品ID查询商品信息 3. 将商品信息加入到购物车中 需要做的逻辑判断 1. 判断购物车是否已有对应商品 2. 如果购物车中没有... 阅读详情

1、需求

对于Teach账号创建的数据,其他用户仅仅只有查询的权限,而不能修改和删除。并且部分接口只允许Teach账号访问

2、实现思路

在删除和修改时往往需要传递数据的id,进而可以通过id查询该数据是否由Teach账号创建。当然我们可以在每个删除和修改接口里面进行判断,但这样照成管控不够集中,并且不利于后续的修改。如果后续又要求对Admin账号创建的数据也做同样的管控,那需要修改的地方会很多。
因此可以通过Aop拦截删除、修改等接口,通过接口的参数中的查询id对应的数据是否由Teach账号创建。

3、实现Demo

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.BiConsumer;

@Order(0)
@Aspect
@Component
public class TeachAccountCheckAop {
    private static final Logger logger = LoggerFactory.getLogger(TeachAccountCheckAop.class);

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private UserInfoUtil userInfoUtil;
    @Autowired
    private ExpInfoService expInfoService;
    @Autowired
    private ExpManualService expManualService;
    @Autowired
    private MaterialInfoService materialInfoService;
    @Autowired
    private SandboxMgtService sandboxMgtService;

    /**
     * 存储每个接口对应的从接口参数中获取id的方式
     */
    private Map<String, BiConsumer<Object, List<Long>>> classMap = new HashMap<>();

    /**
     * 存储仅仅运行Teach账号访问的接口
     */
    private Set<String> onlyTeachApiMethodSet = new HashSet<>();

    {
        onlyTeachApiMethodSet.add("com.huawei.ebg.olblab.controller.ExpInfoController.exportExperiment");
        onlyTeachApiMethodSet.add("com.huawei.ebg.olblab.controller.ExpInfoController.importExperiment");

        /**
         * arg:接口的参数
         * list:用于存储从接口参数中提取的id
         */
        classMap.put("com.huawei.ebg.olblab.controller.ExpInfoController.saveExpBaseInfo", (arg, list) -> {
            ExpBaseInfoDto param = (ExpBaseInfoDto) arg;
            if (Objects.nonNull(param.gettid())) {
                list.add(param.gettid());
            }
        });
        classMap.put("com.huawei.ebg.olblab.controller.ExpManualController.saveExpManualBaseInfo", (arg, list) -> {
            ExpManualBaseDto param = (ExpManualBaseDto) arg;
            if (Objects.nonNull(param.gettid())) {
                list.add(param.gettid());
            }
        });
        classMap.put("com.huawei.ebg.olblab.controller.ExpMaterialInfoController.updateExpMaterialInfo", (arg, list) -> {
            MaterialUpdateDto param = (MaterialUpdateDto) arg;
            if (Objects.nonNull(param.gettid())) {
                list.add(param.gettid());
            }
        });
        classMap.put("com.huawei.ebg.olblab.controller.SandboxMgtController.deleteSandbox", (arg, list) -> {
            SandboxTempDto.Delete param = (SandboxTempDto.Delete) arg;
            if (CollectionUtils.isNotEmpty(param.getSandboxTempIds())) {
                list.addAll(param.getSandboxTempIds());
            }
        });
    }

    @Before("execution(public * com.huawei.ebg.olblab.controller.ExpInfoController.saveExpBaseInfo(..))"
            + "|| execution(public * com.huawei.ebg.olblab.controller.ExpManualController.saveExpManualBaseInfo(..))"
            + "|| execution(public * com.huawei.ebg.olblab.controller.ExpMaterialInfoController.updateExpMaterialInfo(..))"
            + "|| execution(public * com.huawei.ebg.olblab.controller.SandboxMgtController.deleteSandbox(..))")
    public void beforeApiCheck(JoinPoint joinPoint) {
        // 获取当前登录者账号,Teach账号直接结束
        String userAccount = userInfoUtil.getUserAccount(request);
        if (StringUtils.equals(userAccount, ImportAccount.TEACH)) {
            return;
        }

        // 获取切点的方法
        String proxyTargetClass = joinPoint.getSignature().getDeclaringTypeName();
        String proxyTargetMethod = proxyTargetClass + "." + joinPoint.getSignature().getName();

        // 检查接口是否仅Teach能访问
        if (onlyTeachApiMethodSet.contains(proxyTargetMethod)) {
            if (StringUtils.equals(userAccount, ImportAccount.CREAT)) {
                return;
            }
            throw new RuntimeException(ErrorCode.EDU81080); // 仅Teach能访问
        }

        // 从接口参数中获取id
        Object[] args = joinPoint.getArgs();
        BiConsumer<Object, List<Long>> consumer = classMap.get(proxyTargetMethod);
        List<Long> ids = new ArrayList<>();
        for (Object arg : args) {
            if (Objects.isNull(arg)) {
                continue;
            }
            consumer.accept(arg, ids);
        }
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }

        // 不同controller的接口,调用不同的Service查询id对应的数据的创建人是否存在Teach账号创建的数据
        long count = 0L;
        if (StringUtils.equals(proxyTargetClass, ExpInfoController.class.getName())) {
            count = expInfoService.count(Wrappers.lambdaQuery(ExpInfoEntity.class)
                    .eq(ExpInfoEntity::getCreateBy, ImportAccount.TEACH)
                    .in(ExpInfoEntity::getType, ExpType.TYPE_0, ExpType.TYPE_1)
                    .in(ExpInfoEntity::gettid, ids));
        } else if (StringUtils.equals(proxyTargetClass, ExpManualController.class.getName())) {
            count = expManualService.count(Wrappers.lambdaQuery(ExpManualEntity.class)
                    .eq(ExpManualEntity::getCreateBy, ImportAccount.TEACH)
                    .in(ExpManualEntity::gettid, ids));
        } else if (StringUtils.equals(proxyTargetClass, ExpMaterialInfoController.class.getName())) {
            count = materialInfoService.count(Wrappers.lambdaQuery(MaterialInfoEntity.class)
                    .eq(MaterialInfoEntity::getCreateBy, ImportAccount.TEACH)
                    .in(MaterialInfoEntity::gettid, ids));
        } else if (StringUtils.equals(proxyTargetClass, SandboxMgtController.class.getName())) {
            count = sandboxMgtService.count(Wrappers.lambdaQuery(SandboxTempEntity.class)
                    .eq(SandboxTempEntity::getCreatedByName, ImportAccount.TEACH)
                    .in(SandboxTempEntity::getSandboxTempId, ids));
        }
        if (count > 0) {
            throw new RuntimeException(ErrorCode.EDU81080); // 仅Teach能访问
        }
    }
}

4、可优化点

切入点表达式,可以改为自定义注解

基于PHP的网上订餐管理系统的构建与实现 本系统是一个基于 PHP 开发的网上订餐系统,旨在为用户提供便捷、高效的线上订餐服务,同时为管理员提供高效的后台管理功能。项目采用模块化设计,前后端分离,支持功能扩展和多用户操作。本系统通过模块化设计实现了前后端分离,功能完善,具有良好的扩展性和安全性。未来可根据用户需求,进一步优化性能、增强安全性和扩展更多功能,持续提升用户体验和系统可靠性。系统全套资料包含: 源码+万字LW+答辩PPT。 阅读详情

相关推荐

【C++】C++异常语法、使用、规范、异常安全及异常的优缺点

实际中我们可以可以去继承exception类实现自己的异常类。但是实际中很多公司像上面一样自己定义一套异常继承体系。因为C++标准库设计的不够好用。如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。C++ 提供了一系列标准的异常,定义在 中,我们可以在程序中使用这些标准的异常。异常是一种处理错误的方式,

weixin_51692487的博客 1524

学习笔记1:JAVA实现AOP切面编程(增删改自动设置创建/修改时间等信息)

JoinPoint是切入点,可以通过getSignature()方法获取方法签名对象的详细信息,再获取方法上AutoFill注解对象,就可以该方法的操作类型。由于增删改的方法都是对第一个参数对象进行的操作,所有直接取args[0]进行操作,通过反射获取对象的详细方法,再根据操作类型对对象进行相应的操作。明确操作类型,定义一个枚举类,一般是增(Insert)和改(Update)操作,在企业开发中,删除用的是逻辑删除,即。自定义一个注解,用于后续标注在需要被切的方法(数据库增删改方法)上。

qq_59199831的博客 749

Unity3D Lua与C#的相互调用与性能剖析详解

在游戏开发中,经常会遇到Lua与C#之间的相互调用的情况。本文将详细介绍Unity3D中Lua与C#的相互调用的方式,并对其性能进行剖析。对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!一、Lua与C#的相互调用方式Lua调用C#在Unity3D中,可以通过Lua调用C#的方式来实现Lua与C#的相互调用。具体步骤如下:(1)首先需要在Unity3D项目中导入Lua的相关库,例如tolua或者xlua。

weixin_49669470的博客 1213

Spring AOP 完整教程(下篇・企业综合实战 + ThreadLocal

自定义日志标记注解@Target(ElementType.METHOD) // 仅作用于方法// 自定义操作描述Controller 接口添加注解标记@Log("新增部门信息")切面切点匹配注解ThreadLocal = 线程局部变量,为每一条请求线程分配独立私有存储空间,线程之间数据完全隔离、互不干扰。同一 HTTP 请求全程共用一条线程:过滤器→Controller→Service→AOP 切面,全程共享登录用户 ID,无需层层传参。

mgw1413的博客 438

ABAP on HANA/CDS view/AMDP 大乱炖

文章目录1. HANA的三大杀器1.1 内存式数据库1.2 多核架构1.3 列式存储1.3.1 数据压缩1.3.2 并行处理1.3.3 聚集和索引1.3.4 代码下移2. CDS 概念2.1 ABAP 开发环境2.2 OPEN SQL语句2.3 CDS 到底是啥2.4 CDS 类型2.5 创建CDS view3. CDS 实战3.1 Annotation注解3.2 Case 语句3.3 数学计算3.4 字符串表达3.5 货币转换3.6 聚集语句3.7 Join3.8 Union3.9 参数3.10 作为子C

weixin_45689053的博客 4782

CentOS7下Ollama部署全攻略:从安装到自定义端口配置(附国内加速技巧)

本文详细介绍了在CentOS7系统上部署Ollama的完整流程,包括环境准备、模型下载优化、服务化部署及端口配置等关键步骤。特别针对国内网络环境提供了加速安装方案和镜像源配置技巧,帮助开发者快速搭建稳定的本地AI运行环境。

mmm90的博客 288

如何管好数据权限?DataEase 开源 BI 访问控制实战指南

🔒 数据报表发给全公司,结果竞品的销售数据也被看到了?这不是个例,而是很多团队用 BI 工具时的真实隐患。DataEase 作为一款人人可用的开源 BI 工具(Tableau 的开源替代方案),在数据可视化之外,内置了一套完整的权限管理与访问控制机制:从用户角色、资源操作授权,到行级数据隔离,都能在界面上直接配置。 ## 先搞清楚:DataEase 的权限模型长什么样 理解它的关键是一个思路

gitblog_00075的博客 883

模拟IC设计避坑:手把手教你用Cadence仿真恒定跨导轨到轨运放(附完整工艺库文件)

本文详细解析了使用Cadence仿真恒定跨导轨到轨运放的全流程,涵盖电路原理、工艺库配置、尺寸设计及仿真分析。通过1:3电流镜补偿技术实现跨导稳定,提供CSMC 0.25um工艺下的实战案例,帮助工程师规避设计陷阱,提升模拟IC设计效率。

weixin_30952535的博客 494

LangChain Middleware:Agent 里的 AOP 治理层

Claude Code 的 settings.json 支持 permissions.allow、permissions.ask、permissions.deny 等规则,并且规则按 deny、ask、allow 的顺序匹配,先匹配的规则生效。未来真正有价值的 Agent 架构,不会只比谁的 Prompt 写得好,也不会只比谁接了更多工具,而是比谁能把模型、工具、状态、记忆、权限、成本、安全和可观测性组织成一个可长期运行的系统。但能不能执行,不应该由模型决定,而应该由系统的权限、风控、审批和幂等机制决定。

qq_31142237的博客 419

自动驾驶算法/规划决策控制算法面经汇总、学习路线、面经心得

自动驾驶算法学习路线,面试求职大全

qq_41667348的博客 1万+

YOLO26 FP16/INT8混合量化实战:精度无损+速度拉满,边缘设备部署最优解

这是混合量化的灵魂,告诉量化器:哪些层不准动,保留FP16。"""判断是否为量化敏感层 → 是则豁免为FP16返回 True=敏感层(FP16),False=可量化(INT8)"""# 1. 检测头回归分支# 2. 小通道1×1卷积# 3. SiLU 激活# 4. 残差ShortcutYOLO26想要在Jetson、RK3588、昇腾、嵌入式NPU上真正落地,FP16/INT8混合量化是唯一最优解。它的核心逻辑不是玄学,而是工程上的精准取舍能量化的层,全部INT8榨性能;

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 746

Spring Boot安全协助实战:临时授权与操作审计系统实现

在数字化协作日益频繁的今天,认证与授权是系统安全的两大基石。认证解决“你是谁”,授权解决“你能做什么”。然而,实际场景中经常需要把操作能力临时交给他人,比如远程协助、代运维、带粉等,如果直接共享账号密码,极易引发越权操作和难以追溯的安全风险。临时授权机制应运而生:通过限定权限范围、设置有效期和使用次数,并配合操作审计,确保每一次协助行为都在受控边界内。基于Spring Security与JWT技术构建的权限管理方案,能够有效实现最小权限控制、会话管理和异常撤销,即使令牌泄露也能及时阻断风险。该模式可广泛应用

weixin_33836874的博客 390

完美解决Iframe嵌入帆软报表出现跨域cookie写不进去的问题

那报表后续的请求如何加上这个fine_auth_token,通过观察,我们发现,如果给报表url上加上fine_auth_token,后续的请求中的Refer也会有这个fine_auth_token。我们可以这样想,如果帆软内部获取token,如果从cookie中获取不到,就从url上获取,如果url上也获取不到,那么就从请求Refer请求头中获取也可以拿到这个token了。从上面看到,如果从cookie中没有获取到,就从请求头中获取,还是没有就从paramter中获取。

帆软爱好者的专栏 4062

若依后台权限控制深度解析:从RBAC模型到数据权限实战

权限控制是后台管理系统的核心安全机制,其经典实现RBAC(基于角色的访问控制)模型通过将权限与角色绑定,再分配给用户,实现了灵活且可维护的权限管理。这一原理在工程实践中,能够有效支撑菜单、按钮及接口等多层级权限控制,保障系统安全与用户体验。若依(RuoYi)作为广泛采用的开源后台框架,其内置的RBAC方案经过大量项目验证,提供了稳定可靠的权限骨架。在实际应用场景中,开发者常需处理更复杂的**数据权限**问题,例如实现基于部门的数据隔离,这涉及到在SQL查询中动态注入过滤条件。同时,**权限标识**(Perm

weixin_33834075的博客 412

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

基于SpringBoot+Vue剧本杀服务平台的设计与实现

Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。

源码哆哆 862

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Java通用安全模块设计:从认证授权原理到RBAC实现与扩展

身份认证(Authentication)与权限控制(Authorization)是构建安全应用的核心基础。认证负责验证用户身份,授权则决定用户能访问哪些资源。其技术价值在于为系统提供统一、可扩展的安全层,保障数据与操作的安全隔离。在应用场景上,无论是传统Web应用、前后端分离架构,还是微服务与API网关,都需要可靠的安全机制。本文以Java实现为例,深入探讨了如何设计高内聚、低耦合的安全模块,其中认证模块支持可插拔设计,可灵活接入数据库、LDAP等多种验证方式;授权模块则基于经典的RBAC(基于角色的访问控

abc20899的专栏 353

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

i茅台自动预约系统:5分钟实现全流程智能预约的终极解决方案

在当今数字化时代,i茅台自动预约系统为企业用户提供了高效、智能的茅台预约一站式解决方案。通过自动化技术,该系统显著提升了预约成功率,彻底改变了传统手动预约的低效模式,实现了从账号管理到预约执行的全流程智能化处理。 ## 价值主张:解决传统茅台预约的核心痛点 传统茅台预约面临三大核心挑战,而i茅台自动预约系统通过技术创新提供了全面解决方案: **1. 时间窗口精准性问题** 手动预约需要用户在

gitblog_01114的博客 481

【课程设计】流浪动物保护平台的设计与实现 毕业设计 161154

该系统以JSP、Java编程语言、MySQL和Springboot框架等为开发技术,实现了添加、修改、查看、删除系统数据。本系统采取组件化的方式对系统进行拆分,并对数据库中各个表的增删查改、表与表之间的约束关系进行分析与设计,最终实现符合用户需求功能的商业级应用。系统界面简洁大方,布局合理,易操作易上手。对应用户的每一步操作,系统都能高响应地做出反馈。系统具体包含了志愿者管理、宠物信息管理、宠物资讯管理、宠物领养管理、收容捐赠管理、捐赠信息管理等功能,为流浪动物提供一个保护平台,实现对数据的高效、安全管理。

WeiXin_DZbishe的博客 8458

GTE向量模型Web应用GDPR合规审计与日志脱敏实战

向量模型作为处理非结构化文本的核心技术,通过将文本转换为高维向量实现语义理解与相似性检索。其技术原理基于深度学习编码器,将语义信息压缩为稠密向量表示,为智能搜索、推荐等场景提供基础。在工程实践中,模型服务化部署涉及复杂的数据处理链路,确保数据安全与隐私合规成为关键挑战。GDPR等法规对数据处理的最小化、目的限制和安全存储提出了严格要求,尤其在处理用户个人数据时,日志记录环节极易成为敏感信息泄露的风险点。本文聚焦于GTE中文向量模型的多任务Web应用,深入探讨在模型推理、向量存储与检索全链路中,如何实施GDP

adr5970的博客 384

基于SpringBoot+Vue的旅游打卡点的推荐系统设计与实现

Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。

qq_61827376的博客 818

SpringBoot3+Vue3+MySQL在线编程评测系统源码 前后端分离实战

基于 Spring Boot 3 + Vue 3 + MySQL 的前后端分离在线编程评测系统,支持管理员、教师、学生三角色,涵盖题目管理、代码提交评测、班级作业、评分统计、公告日志等完整功能,附万字文档与初始化脚本,适合教学与二次开发。

kangxihuang的博客 17

(附源码)spring boot点餐系统的设计与实现-毕业设计 课程设计 100908

本设计主要实现集人性化、高效率、便捷等优点于一身的点餐系统,完成用户管理、美食资讯、菜品分类、菜品信息、订单中心、餐厅餐桌、就餐预约等功能模块。系统通过浏览器与服务器进行通信,实现数据的交互与变更。只需通过一台电脑,动动手指就可以操作系统,实现数据通信管理。 点餐系统使用Java语言,采用基于 MVC模式的JavaEE技术进行开发,使用 MyEclipse 2017 CI 10 编译器编写,数据方面主要采用的是微软的MySQL关系型数据库来作为数据存储媒介,配合前台HTML+CSS 技术完成系统的开发。

Q_3461074420的博客 1万+

【课程设计】基于微信小程序音乐播放器的设计与实现毕业设计源码271156

登录页面, 搜索, 歌曲播放页面, 歌词滚动 ,播放进度条, 拖动跳转进度条, 上下一曲,暂停,单曲、顺序、随机播放, 我的喜欢, 最近播放

高级程序源的博客 9346

【课程设计】基于Spring Boot的宠物猫店管理系统的设计与实现毕业设计源码140909

登录退出 用户管理 猫猫用品管理 会员中心管理 服务中心管理 订单中心管理 预约管理

高级程序源的博客 9071

【课程设计】spring boot点餐系统的设计与实现 毕业设计源码100908

本设计主要实现集人性化、高效率、便捷等优点于一身的点餐系统,完成用户管理、美食资讯、菜品分类、菜品信息、订单中心、餐厅餐桌、就餐预约等功能模块。系统通过浏览器与服务器进行通信,实现数据的交互与变更。只需通过一台电脑,动动手指就可以操作系统,实现数据通信管理。整个系统的设计过程都充分考虑了数据的安全、稳定及可靠等问题,而且操作过程简单。本系统通过科学的管理方式、便捷的服务提高了工作效率,减少了数据存储上的错误和遗漏。

专业程序开发源的博客 3320
上一篇: 通过sh脚本导入导出docker镜像
下一篇: Spring Boot接口返回Long类型的数据时丢失精度的全局处理
村口老师傅
博客等级 码龄9年 67粉丝 107原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值