小菜家教平台(四):基于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中我们配置的异常。
这里暂时不会出问题,就是返回的信息看上去与全局异常无关联,不整齐,我们修改一下权限异常处理即可。但是我认为这里应该有更好的处理方法,也可能是我的全局异常处理过于简单导致的,如果有大佬看到这里还请指点一下~
总结
今天首先通过自定义AuthenticationEntryPoint和AccessDeniedHandler实现了认证与授权失败的异常捕获,返回适当的状态码。随后,介在项目中实现全局异常处理,捕获运行时异常和系统异常,并统一处理返回。这样,不仅提高了系统的可维护性,还能帮助开发人员快速定位问题并保证前后端的异常响应一致性。
那今天就这样,明天可能暂停一天,整理一下url路径、返回数据等一些与业务相关的内容。如果这篇文章有帮到你的话,还希望多多支持,你的支持就是我的最大动力!
相关文章:
小菜家教平台(四):基于SpringBoot+Vue打造一站式学习管理系统
前言 昨天配置完了过滤器,权限检验,基本的SpringSecurity功能已经配置的差不多了,今天继续开发,明天可能会暂停一天整理一下需求,然后就进行CRUD了。 今日进度 补充SpringSecurity异常处理和全局异常处理器 详细操作…...
解决 Vue3、Vite 和 TypeScript 开发环境下跨域的问题,实现前后端数据传递
引言 本文介绍如何在开发环境下解决 Vite 前端(端口 3000)和后端(端口 80)之间的跨域问题: 在开发环境中,前端使用的 Vite 端口与后端端口不一致,会产生跨域错误提示: Access to X…...
量化交易系统开发-实时行情自动化交易-3.3.数据采集流程
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来说说数据采集流程,后…...
探索PyAV:Python中的多媒体处理利器
文章目录 探索PyAV:Python中的多媒体处理利器第一部分:背景介绍第二部分:PyAV是什么?第三部分:如何安装PyAV?第四部分:简单的库函数使用方法1. 打开文件2. 查看流3. 遍历帧4. 编码帧5. 关闭输出…...
SpringBoot源码解析(三):启动开始阶段
SpringBoot源码系列文章 SpringBoot源码解析(一):SpringApplication构造方法 SpringBoot源码解析(二):引导上下文DefaultBootstrapContext SpringBoot源码解析(三):启动开始阶段 目录 前言一、入口二、SpringApplicationRunListener1、作用…...
C# const与readonly关键字的区别
在C#中,readonly关键字用于定义在对象创建后不能更改的字段。它可以与常量(const)有些相似,但也有显著不同。以下是readonly关键字的一些关键点: 定义与用法: readonly字段可以在类的构造函数中初始化,而const字段必须…...
【数据分享】1901-2023年我国省市县镇四级的逐年降水数据(免费获取/Shp/Excel格式)
之前我们分享过1901-2023年1km分辨率逐月降水栅格数据和Shp和Excel格式的省市县四级逐月降水数据,原始的逐月降水栅格数据来源于彭守璋学者在国家青藏高原科学数据中心平台上分享的数据!基于逐月数据我们采用求年累计值的方法得到逐年降水栅格数据&#…...
hhdb数据库介绍(9-4)
访问安全 权限体系 计算节点有两类用户,一类是计算节点数据库用户,用于操作数据,执行SELECT,UPDATE,DELETE,INSERT等SQL语句。另一类是关系集群数据库可视化管理平台用户,用于管理配置信息。此…...
苍穹外卖的分层所用到的技术以及工具+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(数列的极限为:,limit(s,n,oo))...
css:还是语法
emmet的使用 emmet是一个插件,Emmet 是 Zen Coding 的升级版,由 Zen Coding 的原作者进行开发,可以快速的编写 HTML、CSS 以及实现其他的功能。很多文本编辑器都支持,我们只是学会使用它: 生成html结构 <!-- emme…...
关于 el-table 的合计行问题
目录 一.自定义合计行 二.合计行不展示,只有缩放/变大窗口或者F12弹出后台时才展示 三.合计行出现了表格滚动条下方 四.合计行整体样式的修改 五.合计行单元格样式修改 1.css 2.jsx方式 六.合计行单元格合并 一.自定义合计行 通过 show-summary 属性开启合计…...
解决SVN更新,提交错误乱码
执行清理操作,没有菜单的情况 1.点击TortoiseSVN-设置-如图勾选 注意:下图没有点击上下文菜单勾选清理 选择对应文件目录,执行【清理】操作 2.如果还是乱码,如上操作勾选解除文件锁定, 执行【破除锁定】后再次执行【…...
《Python网络安全项目实战》项目4 编写网络扫描程序
《Python网络安全项目实战》项目4 编写网络扫描程序 项目4 编写网络扫描程序任务4.1 扫描内网有效IP地址任务描述任务分析任务实施任务拓展 任务4.2 编写端口扫描工具任务描述任务分析任务实施相关知识任务评价任务拓展项目评价 项目4 编写网络扫描程序 许多扫描工具是由Pytho…...
Python金融大数据分析概述
💂 个人网站:【 摸鱼游戏】【神级代码资源网站】【海拥导航】💅 想寻找共同学习交流,摸鱼划水的小伙伴,请点击【全栈技术交流群】 金融大数据分析在金融科技领域越来越重要,它涉及从海量数据中提取洞察,为金…...
黑马产品经理
1、合格的产品经理 什么是产品? 什么是产品经理? 想清楚产品怎么做的人。 合格的产品经理 2、产品经理的分类 为什么会有不同的分类? 按服务对象划分 按产品平台划分 公司所属行业不同(不限于以下) 工作内容划分 …...
机器学习——损失函数、代价函数、KL散度
🌺历史文章列表🌺 机器学习——损失函数、代价函数、KL散度机器学习——特征工程、正则化、强化学习机器学习——常见算法汇总机器学习——感知机、MLP、SVM机器学习——KNN机器学习——贝叶斯机器学习——决策树机器学习——随机森林、Bagging、Boostin…...
首次超越扩散模型和非自回归Transformer模型!字节开源RAR:自回归生成最新SOTA!
文章链接:https://arxiv.org/pdf/2411.00776 项目链接:https://yucornetto.github.io/projects/rar.html 代码&模型链接:https://github.com/bytedance/1d-tokenizer 亮点直击 RAR(随机排列自回归训练策略)&#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可以循环玩 两个板子,内板子放0,外板子放* set函数初始化两个板子 …...
20. 类模板
一、什么是类模板 类模板用于建立一个通用类,类中的成员数据类型可以不具体指定,用一个虚拟的类型来代替。它的语法格式如下: template<typename T>类模板与函数模板相比主要有两点区别:1) 类模板没有自动类型推导的方式。…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
