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

小菜家教平台(四):基于SpringBoot+Vue打造一站式学习管理系统

前言

昨天配置完了过滤器,权限检验,基本的SpringSecurity功能已经配置的差不多了,今天继续开发,明天可能会暂停一天整理一下需求,然后就进行CRUD了。

今日进度

补充SpringSecurity异常处理和全局异常处理器

详细操作

一、补充SpringSecurity异常处理器

当我们没有进行异常处理,项目如果出现了问题,我们很难排查,同时进行异常处理后,返回的数据就比较有规范,可以让前端的开发看懂。

比如我们现在使用一个错误的密码进行登录,Apifox显示403,这对吗?不太对,因为403是用户未授权,而我们这里是认证的问题,应该返回401才正确。这就导致今天检查的时候找了好久,最后才发现是密码写错了,如果返回信息是401,那不是就很快就发现问题了。因此,异常处理还是很重要的。

在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。

​ 如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint 对象的方法去进行异常处理,返回401。

​ 如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理,返回403。

​ 所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置给SpringSecurity即可。

听上去听复杂的?但是实现并不复杂

只要重写AuthenticationException和AccessDeniedHandler方法并添加到配置中即可。

@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {ResponseResult result = new ResponseResult(HttpStatus.UNAUTHORIZED.value(), "用户认证失败,请重新登录");String json = JSON.toJSONString(result);WebUtils.renderString(response,json);}
}
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {ResponseResult result = new ResponseResult(HttpStatus.FORBIDDEN.value(), "权限不足");String json = JSON.toJSONString(result);WebUtils.renderString(response,json);}
}
@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers("/user/login").anonymous().antMatchers("/hello/**").hasRole("ADMIN")//对于/hello的路径,只有ADMIN权限的用户才能访问.antMatchers("/ok/**").hasAnyRole("ADMIN","TEACHER")//对于/ok的路径,ADMIN和USER权限的用户都可以访问// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();//添加自定义过滤器http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);//添加自定义异常处理http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);}

这样,我们进行测试就能很快的发现问题了,如下图:

二、全局异常处理

上面我们只进行了有关SpringSecurity的异常处理,那要是其他地方出现异常怎么办?所以我们要进行全局的异常处理。因为项目不太大,所以这里使用了一个简单的全局异常处理,要是后面项目实现功能很多的话,可以考虑使用复杂完整的全局异常处理。

首先,为了进行测试,我们先编写两个异常方法,一个是数组越界,一个是除0

@RequestMapping("/ok/t1")public int test1(){List<Integer> integers = new ArrayList<>();for (int i = 0; i < 10; i++){integers.add(i);}//故意数组过界进行异常测试for (int i = 0; i < 20; i++){System.out.println(integers.get(i));}return 1;}@RequestMapping("/ok/t2")public int test2(){int t = 10/0;System.out.println(t);return 1;}

接着编写一下全局异常类

@RestControllerAdvice
public class GlobalExceptionHandler {// 捕获所有的 RuntimeException 异常@ExceptionHandler(value = {RuntimeException.class})public ResponseResult<String> handleRuntimeException(RuntimeException e) {// 这里会捕获到一些业务异常,或者其他运行时异常return new ResponseResult<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "运行时异常: " + e.getMessage());}// 捕获所有其他的 Exception 异常@ExceptionHandler(value = {Exception.class})public ResponseResult<String> handleException(Exception e) {// 处理一些无法捕获的异常return new ResponseResult<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统异常: " + e.getMessage());}
}

并在统一返回信息中添加一个方法

public static ResponseResult<String> error(String message){return new ResponseResult<>(500,message,null);}

这样就行了,是不是很简单。接下来进行测试。

密码错误:

权限异常:

数组越界:

除零:

这样项目中的异常就可以成功处理了,但是有没有发现一个小问题:

我们原先配置的SpringSecurity中的认证异常被全局异常覆盖了,但是权限异常还是SpringSecurity中我们配置的异常。

这里暂时不会出问题,就是返回的信息看上去与全局异常无关联,不整齐,我们修改一下权限异常处理即可。但是我认为这里应该有更好的处理方法,也可能是我的全局异常处理过于简单导致的,如果有大佬看到这里还请指点一下~

总结

今天首先通过自定义AuthenticationEntryPointAccessDeniedHandler实现了认证与授权失败的异常捕获,返回适当的状态码。随后,介在项目中实现全局异常处理,捕获运行时异常和系统异常,并统一处理返回。这样,不仅提高了系统的可维护性,还能帮助开发人员快速定位问题并保证前后端的异常响应一致性。

那今天就这样,明天可能暂停一天,整理一下url路径、返回数据等一些与业务相关的内容。如果这篇文章有帮到你的话,还希望多多支持,你的支持就是我的最大动力!

相关文章:

小菜家教平台(四):基于SpringBoot+Vue打造一站式学习管理系统

前言 昨天配置完了过滤器&#xff0c;权限检验&#xff0c;基本的SpringSecurity功能已经配置的差不多了&#xff0c;今天继续开发&#xff0c;明天可能会暂停一天整理一下需求&#xff0c;然后就进行CRUD了。 今日进度 补充SpringSecurity异常处理和全局异常处理器 详细操作…...

解决 Vue3、Vite 和 TypeScript 开发环境下跨域的问题,实现前后端数据传递

引言 本文介绍如何在开发环境下解决 Vite 前端&#xff08;端口 3000&#xff09;和后端&#xff08;端口 80&#xff09;之间的跨域问题&#xff1a; 在开发环境中&#xff0c;前端使用的 Vite 端口与后端端口不一致&#xff0c;会产生跨域错误提示&#xff1a; Access to X…...

量化交易系统开发-实时行情自动化交易-3.3.数据采集流程

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来说说数据采集流程&#xff0c;后…...

探索PyAV:Python中的多媒体处理利器

文章目录 探索PyAV&#xff1a;Python中的多媒体处理利器第一部分&#xff1a;背景介绍第二部分&#xff1a;PyAV是什么&#xff1f;第三部分&#xff1a;如何安装PyAV&#xff1f;第四部分&#xff1a;简单的库函数使用方法1. 打开文件2. 查看流3. 遍历帧4. 编码帧5. 关闭输出…...

SpringBoot源码解析(三):启动开始阶段

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 目录 前言一、入口二、SpringApplicationRunListener1、作用…...

C# const与readonly关键字的区别

在C#中&#xff0c;readonly关键字用于定义在对象创建后不能更改的字段。它可以与常量(const)有些相似&#xff0c;但也有显著不同。以下是readonly关键字的一些关键点&#xff1a; 定义与用法&#xff1a; readonly字段可以在类的构造函数中初始化&#xff0c;而const字段必须…...

【数据分享】1901-2023年我国省市县镇四级的逐年降水数据(免费获取/Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月降水栅格数据和Shp和Excel格式的省市县四级逐月降水数据&#xff0c;原始的逐月降水栅格数据来源于彭守璋学者在国家青藏高原科学数据中心平台上分享的数据&#xff01;基于逐月数据我们采用求年累计值的方法得到逐年降水栅格数据&#…...

hhdb数据库介绍(9-4)

访问安全 权限体系 计算节点有两类用户&#xff0c;一类是计算节点数据库用户&#xff0c;用于操作数据&#xff0c;执行SELECT&#xff0c;UPDATE&#xff0c;DELETE&#xff0c;INSERT等SQL语句。另一类是关系集群数据库可视化管理平台用户&#xff0c;用于管理配置信息。此…...

苍穹外卖的分层所用到的技术以及工具+jwt令牌流程图(jwt验证)

分层用到的技术以及工具: jwt令牌流程图:...

Python——数列1/2,2/3,3/4,···,n/(n+1)···的一般项为Xn=n/(n+1),当n—>∞时,判断数列{Xn}是否收敛

没注释的源代码 from sympy import * n symbols(n) s n/(n1) print(数列的极限为&#xff1a;,limit(s,n,oo))...

css:还是语法

emmet的使用 emmet是一个插件&#xff0c;Emmet 是 Zen Coding 的升级版&#xff0c;由 Zen Coding 的原作者进行开发&#xff0c;可以快速的编写 HTML、CSS 以及实现其他的功能。很多文本编辑器都支持&#xff0c;我们只是学会使用它&#xff1a; 生成html结构 <!-- emme…...

关于 el-table 的合计行问题

目录 一.自定义合计行 二.合计行不展示&#xff0c;只有缩放/变大窗口或者F12弹出后台时才展示 三.合计行出现了表格滚动条下方 四.合计行整体样式的修改 五.合计行单元格样式修改 1.css 2.jsx方式 六.合计行单元格合并 一.自定义合计行 通过 show-summary 属性开启合计…...

解决SVN更新,提交错误乱码

执行清理操作&#xff0c;没有菜单的情况 1.点击TortoiseSVN-设置-如图勾选 注意&#xff1a;下图没有点击上下文菜单勾选清理 选择对应文件目录&#xff0c;执行【清理】操作 2.如果还是乱码&#xff0c;如上操作勾选解除文件锁定&#xff0c; 执行【破除锁定】后再次执行【…...

《Python网络安全项目实战》项目4 编写网络扫描程序

《Python网络安全项目实战》项目4 编写网络扫描程序 项目4 编写网络扫描程序任务4.1 扫描内网有效IP地址任务描述任务分析任务实施任务拓展 任务4.2 编写端口扫描工具任务描述任务分析任务实施相关知识任务评价任务拓展项目评价 项目4 编写网络扫描程序 许多扫描工具是由Pytho…...

Python金融大数据分析概述

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【海拥导航】&#x1f485; 想寻找共同学习交流&#xff0c;摸鱼划水的小伙伴&#xff0c;请点击【全栈技术交流群】 金融大数据分析在金融科技领域越来越重要&#xff0c;它涉及从海量数据中提取洞察&#xff0c;为金…...

黑马产品经理

1、合格的产品经理 什么是产品&#xff1f; 什么是产品经理&#xff1f; 想清楚产品怎么做的人。 合格的产品经理 2、产品经理的分类 为什么会有不同的分类&#xff1f; 按服务对象划分 按产品平台划分 公司所属行业不同&#xff08;不限于以下&#xff09; 工作内容划分 …...

机器学习——损失函数、代价函数、KL散度

&#x1f33a;历史文章列表&#x1f33a; 机器学习——损失函数、代价函数、KL散度机器学习——特征工程、正则化、强化学习机器学习——常见算法汇总机器学习——感知机、MLP、SVM机器学习——KNN机器学习——贝叶斯机器学习——决策树机器学习——随机森林、Bagging、Boostin…...

首次超越扩散模型和非自回归Transformer模型!字节开源RAR:自回归生成最新SOTA!

文章链接&#xff1a;https://arxiv.org/pdf/2411.00776 项目链接&#xff1a;https://yucornetto.github.io/projects/rar.html 代码&模型链接&#xff1a;https://github.com/bytedance/1d-tokenizer 亮点直击 RAR&#xff08;随机排列自回归训练策略&#xff09;&#x…...

C语言最简单的扫雷实现(解析加原码)

头文件 #define ROW 9 #define COL 9 #define ROWS ROW2 #define COLS COL2 #include <stdio.h> #include <stdlib.h> #include <time.h> #define numlei 10do while可以循环玩 两个板子&#xff0c;内板子放0&#xff0c;外板子放* set函数初始化两个板子 …...

20. 类模板

一、什么是类模板 类模板用于建立一个通用类&#xff0c;类中的成员数据类型可以不具体指定&#xff0c;用一个虚拟的类型来代替。它的语法格式如下&#xff1a; template<typename T>类模板与函数模板相比主要有两点区别&#xff1a;1) 类模板没有自动类型推导的方式。…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...