Springboot与SpringSecurity使用(2):授权、自定义异常处理

一、用户授权

        在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行权限校验。在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的权限信息。判断当前用户是否拥有访问当前资源所需的权限。SpringSecurity中的Authentication类如下所示:

public interface Authentication extends Principal, Serializable {//权限数据列表Collection<? extends GrantedAuthority> getAuthorities();Object getCredentials();Object getDetails();Object getPrincipal();boolean isAuthenticated();void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

        前面登录时执行loadUserByUsername方法时,return new CustomUser(sysUser, Collections.emptyList());后面的空数据对接就是返回给Spring Security的权限数据。登录时我们把权限数据保存到redis中(用户名为key,权限数据为value即可),这样通过token获取用户名即可拿到权限数据,这样就可构成出完整的Authentication对象。

1、修改loadUserByUsername接口方法

package com.ywz.security.service;import com.ywz.pojo.SysUser;
import com.ywz.security.CustomUser;
import com.ywz.service.SysUserService;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;/*** 类描述 -> 实现UserDetailsService接口,重写方法** @Author: ywz* @Date: 2024/07/28*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService{@Resourceprivate SysUserService sysUserService;@Resourceprivate SysMenuService sysMenuService; // 用于获取用户权限@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser sysUser = sysUserService.queryByUsername(username);if (Objects.isNull(sysUser)){throw new UsernameNotFoundException("用户名不存在!");}if(sysUser.getStatus() == 0) {throw new RuntimeException("账号已停用");}// 获取用户权限List<String> userPermsList = sysMenuService.findUserPermsList(sysUser.getId());List<SimpleGrantedAuthority> authorities = new ArrayList<>();for (String perm : userPermsList) {authorities.add(new SimpleGrantedAuthority(perm.trim()));}return new CustomUser(sysUser, authorities);}
}

2、修改配置类

        配置类添加注解,开启基于方法的安全认证机制,也就是说在web层的controller启用注解机制的安全确认。

/*** 类描述 -> SpringSecurity配置类** @Author: ywz* @Date: 2024/07/28*/
@Configuration
@EnableWebSecurity // 是开启SpringSecurity的默认行为
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启SpringSecurity注解
public class SecurityConfig {/***内容和第一篇文章一致,所以省略****/
}

3、控制controller层接口权限

        Spring Security默认是禁用注解的,要想开启注解,需要在继承WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解,来判断用户对某个控制层的方法是否具有访问权限。通过@PreAuthorize标签控制controller层接口权限:

/*** 类描述 -> 角色前端控制器** @Author: ywz* @Date: 2024/07/28*/
public class SysRoleController {@Autowiredprivate SysRoleService sysRoleService;/*** 方法描述 -> 角色分页查询** @Return: @return {@link R }<{@link Page }* @Author: ywz* @Date: 2024/07/28*/@PreAuthorize("hasAuthority('policy:sysRole:list')") // 需要拥有该权限的用户才可以访问@ApiOperation(value = "获取分页列表")@GetMapping("/{page}/{limit}")public Result list(@ApiParam(name = "page", value = "当前页码", required = true)@PathVariable Long page,@ApiParam(name = "limit", value = "每页记录数", required = true)@PathVariable Long limit,@ApiParam(name = "roleQueryVo", value = "查询对象", required = false)SysRoleQueryVo roleQueryVo) {Page<SysRole> pageParam = new Page<>(page, limit);IPage<SysRole> pageModel = sysRoleService.selectPage(pageParam, roleQueryVo);return Result.ok(pageModel);}// ... 以下省略
}

4、测试服务器端权限

        登录后台,分配权限进行测试,页面如果添加了按钮权限控制,可临时去除方便测试。测试结论:

  1. ​ 分配了权限的能够成功返回接口数据
  2. ​ 没有分配权限的会抛出异常:org.springframework.security.access.AccessDeniedException: 不允许访问

二、异常处理

        如果希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。

  • 如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。
  • ​ 如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。

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

  1. 扩展Spring Security异常处理类:AccessDeniedHandler、AuthenticationEntryPoint
  2. ​ 在spring boot全局异常统一处理

        注意:如果系统实现了全局异常处理,那么全局异常首先会获取AccessDeniedException异常,要想Spring Security扩展异常生效,必须在全局异常再次抛出该异常。

        自定义异常实现类:

package com.ywz.security.filter;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** 类描述 -> 认证失败处理类** @Author: ywz* @Date: 2024/07/28*/
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {/*** 方法描述 -> 认证失败处理** @Return:* @Author: ywz* @Date: 2024/07/28*/@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {response.setStatus(200);// 自定义响应码枚举int code = ResultCodeEnum.LOGIN_AUTH.getCode();String msg = "认证失败,无法访问系统资源";response.setContentType("application/json;charset=UTF-8");Map<String, Object> result = new HashMap<>();result.put("msg", msg);result.put("code", code);String s = new ObjectMapper().writeValueAsString(result);response.getWriter().println(s);}
}
package com.ywz.security.filter;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** 类描述 -> 授权失败处理类** @Author: ywz* @Date: 2024/07/28*/
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {/*** 方法描述 -> 授权失败处理** @Author: ywz* @Date: 2024/07/28*/@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {int code = ResultCodeEnum.PERMISSION.getCode();response.setStatus(200);response.setContentType("application/json;charset=UTF-8");String msg = "权限不足,无法访问系统资源";Map<String, Object> result = new HashMap<>();result.put("msg", msg);result.put("code", code);String s = new ObjectMapper().writeValueAsString(result);response.getWriter().println(s);}
}

        配置给SpringSecurity,在SecurityConfig中先注入对应的处理器:

    @Resourceprivate AccessDeniedHandlerImpl accessDeniedHandler;@Resourceprivate AuthenticationEntryPointImpl authenticationEntryPoint;

        然后在使用HttpSecurity对象的方法中添加相应配置。

return  http// 基于 token,不需要 csrf.csrf().disable().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler)// ... 以下省略 

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

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

相关文章

2024-HW最新漏洞整理及相应解决方案(一)

前言&#xff1a; 漏洞是基于部分安全厂家、软件厂商的公众号或官方网站&#xff0c;以及一些非官方渠道等途径整理的HW安全漏洞情报&#xff0c;情报里附含漏洞详情和解决方案。护网期间我将持续更新分享&#xff0c;希望可以在护网期间帮助到大家 漏洞 用友U8CLOUDv3.6版本以…

c++初阶篇(七):类和对象(日期类)

1.头文件 定义了日期类&#xff0c;给出了类成员变量及成员函数的声明 #pragma once #include<iostream> #include<assert.h> using namespace std; class Date{public:friend ostream& operator<<(ostream& out, const Date& d);friend istre…

计算机网络中的 IPv6 部署与转换

背景介绍 随着互联网的迅速发展&#xff0c;IPv4 地址资源日益枯竭&#xff0c;无法满足未来互联网设备连接的需求。为了解决这一问题&#xff0c;IPv6 应运而生。IPv6&#xff08;互联网协议第六版&#xff09;提供了比 IPv4 更大的地址空间、更好的安全性和扩展性。然而&…

【多模态大模型】 ALBEF in NeurIPS 2021

一、引言 论文&#xff1a; Align before Fuse: Vision and Language Representation Learning with Momentum Distillation 作者&#xff1a; Salesforce Research 代码&#xff1a; ALBEF 特点&#xff1a; 该方法使用ViT进行图像特征提取&#xff0c;提出将BERT分两部分&am…

Cocos Creator2D游戏开发(3)-飞机大战(1)-背景动起来

资源见: https://pan.baidu.com/s/1cryYNdBOry5A4YEEcLwhDQ?pwdzual 步骤 1, 让背景动起来 2, 玩家飞机显现,能操控,能发射子弹 3.敌机出现 4. 碰撞效果(子弹和敌机,敌机和玩家) 5. 积分和游戏结束 6. 游戏存档,对接微信小游戏,保存历史最高分 7. cocos发布到微信小游戏 资源…

探索Python的进度条神器:tqdm

文章目录 探索Python的进度条神器&#xff1a;tqdm一、背二、tqdm简介三、安装tqdm四、tqdm的五个简单使用示例五、tqdm在不同场景下的应用六、常见问题及解决方案七、总结 探索Python的进度条神器&#xff1a;tqdm 一、背 景&#xff1a;为什么选择tqdm&#xff1f; 在Python…

苦学Opencv的第十四天:人脸检测和人脸识别

Python OpenCV入门到精通学习日记&#xff1a;人脸检测和人脸识别 前言 经过了十三天的不懈努力&#xff0c;我们终于也是来到了人脸检测和人脸识别啦&#xff01;相信大家也很激动吧。接下来我们开始吧&#xff01; 人脸识别是基于人的脸部特征信息进行身份识别的一种生物识…

Spring 常用的三种拦截器详解

前言 在开发过程中&#xff0c;我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 AOP、 Interceptor 、 Filter&#xff0c;但其实很多人并不知道什么时候用AOP&#xff0c;什么时候用Interceptor&#xff0c;什么时候用Filter&#xff0c;也不知道其拦截顺序&am…

spring —— 事务管理器

事务管理主要针对数据源进行操作&#xff1a;在数据库方面&#xff0c;通过 TransactionManager 事务管理器进行管理&#xff0c;表明一旦出现错误&#xff0c;该数据源的所有数据全部复原。那么数据库如何判断是否发生了错误呢&#xff1f;这就需要在代码方面&#xff0c;通过…

TreeSize-Pro-9.0.1磁盘占用分析工具

软件下载 TreeSize-Pro-9.0.1磁盘占用分析工具是一个热门的 精品软件 网站&程序 这款软件操作简单&#xff0c;选择需要分析的磁盘开始分析后&#xff0c;左侧列表中很明显的看到磁盘下各个文件夹的大小。 选择文件夹后能在右边显示文件夹下的内容&#xff0c;并且也能显…

抖音直播弹幕数据逆向:websocket和JS注入

&#x1f50d; 思路与步骤详解 &#x1f575;️‍♂️ 思路介绍 首先&#xff0c;我们通过抓包工具进入的直播间&#xff0c;捕获其网络通信数据&#xff0c;重点关注WebSocket连接。发现直播弹幕数据通过WebSocket传输&#xff0c;这种方式比传统的HTTP更适合实时数据的传输。…

前端基于 axios 实现批量任务调度管理器 demo

一、背景介绍 这是一个基于 axios 实现的批量任务调度管理器的 demo。它使用了axios、promise 等多种技术和原理来实现批量处理多个异步请求&#xff0c;并确保所有请求都能正确处理并报告其状态。 假设有一个场景&#xff1a;有一个任务列表&#xff0c;有单个任务的处理功能…

alova的二次封装

alova的二次封装 为什么要进行alova二次封装二次封装的具体步骤1. index.js2. api.js3. service.js4. 在Vue中使用 为什么要进行alova二次封装 上篇文章介绍了alova的基本使用方法&#xff1a;alova详解&#xff0c;对比axios&#xff0c;alova的具体使用&#xff0c;但是每次…

【Qt】QLCDNumberQProgressBarQCalendarWidget

目录 QLCDNumber 倒计时小程序 相关属性 QProgressBar 进度条小程序 相关设置 QLCDNumber QLCDNumber是Qt框架中用于显示数字或计数值的小部件。通常用于显示整数值&#xff0c;例如时钟、计时器、计数器等 常用属性 属性说明intValueQLCDNumber显示的初始值(int类型)va…

企业版邮箱适用哪些企业

企业邮箱适合哪些企业呢&#xff1f;企业版邮箱为企业提供安全、稳定、集成的邮件服务&#xff0c;支持初创、中小、大型企业及特定行业需求。ZohoMail作为优质提供商&#xff0c;提供多层安全措施、移动访问、集成能力及定制化服务&#xff0c;满足不同规模企业需求。 一、企…

2023年系统架构设计师考试总结

原文链接&#xff1a;https://www.cnblogs.com/zhaotianff/p/17812187.html 上周六参加了2023年系统架构设计师考试&#xff0c;这次考试与以前有点区别&#xff0c;是第一次采用电子化考试&#xff0c;也是教材改版后的第一次考试。 说说考前准备&#xff1a;为了准备这次考试…

流媒体服务器Nginx with RTMP安装和配置

以下是在 CentOS 7.6 上安装和配置 Nginx with RTMP module 的详细步骤&#xff1a; 1. 安装 Nginx with RTMP 模块 1.1 安装必要的依赖和工具 首先&#xff0c;更新系统并安装必要的依赖包&#xff1a; sudo yum update -y sudo yum install -y epel-release sudo yum ins…

基于微信小程序的校园警务系统/校园安全管理系统/校园出入管理系统

摘要 伴随着社会以及科学技术的发展&#xff0c;小程序已经渗透在人们的身边&#xff0c;小程序慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;小程序这一名词已不陌生&#xff0c;越来越多的学校机构等都会定制一款属于自己个性化的小程…

利用arthas热更新class文件

利用arthas热更新class文件 背景&#xff1a;发现一个bug&#xff0c;家里难以复现&#xff0c;需要在现场环境更新几行代码验证。 arthas-boot version: 3.7.1 java -jar arthas-boot.jar启动arthas 1、利用arthas的sc命令查找确定类名称 sc com.**2、反编译为java文件 …

《通讯世界》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《通讯世界》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定学术期刊。 问&#xff1a;《通讯世界》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a;科学技术部 主办单位&#xff1a;中国科学技…