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

SpringSecurity授权

文章目录

  • 工具类
  • 使用
  • 自定义失败处理
    • 代码
    • 配置
  • 跨域
  • 其他权限授权
    • hasAnyAuthority
    • 自定义权限校验方法
    • 基于配置的权限控制

工具类

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class WebUtils {/*** 将字符串渲染到客户端** @param response 渲染对象* @param string   待渲染的字符串* @return null*/public static String renderString(HttpServletResponse response, String string) {try {response.setStatus (200);response.setContentType ("application/json");response.setCharacterEncoding ("utf-8");response.getWriter ().print (string);} catch (IOException e) {e.printStackTrace ();}return null;}
}

使用

启动类加注解**@EnableGlobalMethodSecurity(prePostEnabled = true)**

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
@MapperScan("com.example.security.mapper")
public class SecurityApplication {public static void main(String[] args) {SpringApplication.run (SecurityApplication.class, args);}}

接口前添加**@PreAuthorize**注解,需要xxx权限才可以执行

@RestController
public class HelloController {@RequestMapping("/hello")@PreAuthorize("hasAuthority('test')")public String hello(){return "hello";}
}

封装 权限信息

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;@Data
@NoArgsConstructor
public class LoginUser implements UserDetails {private User user;//存储权限信息private List<String> permissions;public LoginUser(User user, List<String> permissions) {this.user = user;this.permissions = permissions;}//存储SpringSecurity所需要的权限信息的集合@JSONField(serialize = false)// 不序列化到 redisprivate List<GrantedAuthority> authorities;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {/*** 如果存在权限,直接返回*/if (authorities != null) {return authorities;}// 把permissions中字符串类型的权限信息转换成GrantedAuthority对象存入authorities中authorities = permissions.stream ().map (SimpleGrantedAuthority::new).collect (Collectors.toList ());return authorities;}@Overridepublic String getPassword() {return user.getPassword ();}@Overridepublic String getUsername() {return user.getUserName ();}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
}

修改UserDetailsServiceloadUserByUsername方法,封装授权信息

@Autowired
private UserMapper userMapper;@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查询用户信息LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<> ();queryWrapper.eq (User::getUserName, username);User user = userMapper.selectOne (queryWrapper);if (user == null) {// 用户不存在throw new RuntimeException ("用户不存在");}// TODO  根据用户查询权限信息 添加到 LoginUser中List<String> permissionKeyList = menuMapper.selectPermsByUserId (user.getId ());// 测试写法// List<String> list = new ArrayList<> (Arrays.asList("test"));return new LoginUser (user, permissionKeyList);
}

修改JwtAuthenticationTokenFilterdoFilterInternal方法,

@Autowiredprivate StringRedisTemplate redisTemplate;/*** 对于需要登录的接口进行拦截* 看看用户信息是否存在** @param request* @param response* @param filterChain* @throws ServletException* @throws IOException*/@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 获取 tokenString token = request.getHeader ("token");if (!StringUtils.hasText (token)) {// 不携带token,放行filterChain.doFilter (request, response);return;}//解析tokenString userId;try {Claims claims = JwtUtil.parseJWT (token);userId = claims.getSubject ();} catch (Exception e) {e.printStackTrace ();throw new RuntimeException ("token非法");}//从redis中获取用户信息String redisKey = "login:" + userId;LoginUser loginUser = JSONObject.parseObject (redisTemplate.opsForValue ().get (redisKey), LoginUser.class);if (Objects.isNull (loginUser)) {// 没有token,就是未登录throw new RuntimeException ("用户未登录");}//存入SecurityContextHolder//TODO 获取权限信息封装到Authentication中UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken (loginUser, null, loginUser.getAuthorities ());SecurityContextHolder.getContext ().setAuthentication (authenticationToken);// 放行filterChain.doFilter (request, response);}

自定义失败处理

代码

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

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


/*** 授权失败*/
@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);}
}
/*** 认证失败*/
@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);}
}

配置

public class SecurityConfig extends WebSecurityConfigurerAdapter

@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;@Autowired
private AccessDeniedHandler accessDeniedHandler;
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);

跨域

①先对SpringBoot配置,运行跨域请求

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {// 设置允许跨域的路径registry.addMapping ("/**")// 设置允许跨域请求的域名.allowedOriginPatterns ("*")// 是否允许cookie.allowCredentials (true)// 设置允许的请求方式.allowedMethods ("GET", "POST", "DELETE", "PUT")// 设置允许的header属性.allowedHeaders ("*")// 跨域允许时间.maxAge (3600);}
}

②开启SpringSecurity的跨域访问

//允许跨域
http.cors();

其他权限授权

hasAnyAuthority

// hasAnyAuthority 有其中的任何一个权限
@PreAuthorize("hasAnyAuthority('admin','test','system:dept:list')")
public String hello(){return "hello";
}

自定义权限校验方法

import com.example.security.vo.LoginUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;import java.util.List;@Component("ex")
public class XDExpressionRoot {public boolean hasAuthority(String authority) {// 获取当前用户的权限Authentication authentication = SecurityContextHolder.getContext ().getAuthentication ();LoginUser loginUser = (LoginUser) authentication.getPrincipal ();List<String> permissions = loginUser.getPermissions ();// 判断用户权限集合中 是否存在authorityreturn permissions.contains (authority);}
}

@ex代表这个Bean对象

@PostMapping("/user/login")
@PreAuthorize("@ex.hasAuthority('xd')")
public ResponseResult login(@RequestBody User user) {return loginServcie.login (user);
}

基于配置的权限控制

在配置类中使用配置的方式 对资源进行权限控制

@Override
protected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers("/user/login").anonymous().antMatchers("/testCors").hasAuthority("system:dept:list")// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();// 添加过滤器http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 配置异常处理器http.exceptionHandling()// 配置认证失败处理器.authenticationEntryPoint(authenticationEntryPoint)// 配置授权失败处理器.accessDeniedHandler(accessDeniedHandler);// 允许跨域http.cors();
}

相关文章:

SpringSecurity授权

文章目录工具类使用自定义失败处理代码配置跨域其他权限授权hasAnyAuthority自定义权限校验方法基于配置的权限控制工具类 import javax.servlet.http.HttpServletResponse; import java.io.IOException;public class WebUtils {/*** 将字符串渲染到客户端** param response 渲…...

学习 Python 之 Pygame 开发坦克大战(一)

学习 Python 之 Pygame 开发坦克大战&#xff08;一&#xff09;Pygame什么是Pygame?初识pygame1. 使用pygame创建窗口2. 设置窗口背景颜色3. 获取窗口中的事件4. 在窗口中展示图片(1). pygame中的直角坐标系(2). 展示图片(3). 给部分区域设置颜色5. 在窗口中显示文字6. 播放音…...

2.5|iot冯|方元-嵌入式linux系统开发入门|2.13+2.18

一、 Linux 指令操作题&#xff08;共5题&#xff08;共 20 分&#xff0c;每小题 4分&#xff09;与系统工作、系统状态、工作目录、文件、目录、打包压缩与搜索等主题相关。1.文件1.1文件属性1.2文件类型属性字段的第1个字符表示文件类型&#xff0c;后9个字符中&#xff0c;…...

一起Talk Android吧(第四百九十六回:自定义View实例二:环形进度条)

文章目录 知识回顾实现思路实现方法示例代码各位看官们大家好,上一回中咱们说的例子是"如何使用Java版MQTT客户端",这一回中咱们说的例子是"自定义View实例二:环形进度条"。闲话休提,言归正转,让我们一起Talk Android吧! 知识回顾 看官们,我们又回…...

上传图片尺寸校验

使用方法 ● Image ● URL ● onload代码&#xff1a; async validImageSize(file, imgWidth, imgHeight) {const img new Image()img.src URL.createObjectURL(file)const { w, h } await new Promise((resolve, reject) > {img.onload () > {const { width: w, he…...

【Python】缺失值处理和拉格朗日插值法(含源代码实现)

目录&#xff1a;缺失值处理和拉格朗日插值法一、前言二、理论知识三、代码实现一、前言 对于含有缺失值的数据集&#xff0c;如果通过删除小部分记录达到既定的目标&#xff0c;那么删除含有缺失值的记录的方法是最有效的。然而&#xff0c;这种方法也有很多问题&#xff0c;…...

SpringCloudAlibaba-Sentinel

一、介绍官网&#xff1a;https://github.com/alibaba/Sentinel/下载jar包,启动,访问http://localhost:8080/创建module添加如下依赖<!--SpringCloud ailibaba sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring…...

【程序化天空盒】过程记录02:云扰动 边缘光 消散效果

写在前面 写在前面唉&#xff0c;最近筋疲力竭&#xff0c;课题组的东西一堆没做&#xff0c;才刚刚开始带着思考准备练习作品&#xff0c;从去年5月份开始到现在真得学了快一年了&#xff0c;转行学其他的真的好累&#xff0c;&#xff0c;不过还是加油&#xff01; 下面是做…...

链表OJ(三) 反转链表合集

目录 反转链表 反转链表 II 链表中的节点每k个一组翻转 描述 给定一个单链表的头结点pHead(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 数据范围&#xff1a; 0≤n≤10000≤…...

SQLSERVER2019安装步骤过程

第一步官网下载SQLSERVER软件包 目前官网只能下载最新版本2022版本。 通过迅雷下载网址 SQL Server 2019 Enterprise (x64) - DVD (Chinese-Simplified)企业版 ed2k://|file|cn_sql_server_2019_enterprise_x64_dvd_2bfe815a.iso|1632086016|58C258FF0F1D006DD3C1F5F17AF3E…...

Java模块化概述

3 模块化 3.1 模块化概述 Java语言随着这些年的发展已经成为了一]影响深远的编程语言&#xff0c;无数平台,系统都采用Java语言编写。但是&#xff0c;伴随着发展&#xff0c;Java也越来越庞大&#xff0c;逐渐发展成为-门“臃肿” 的语言。而且&#xff0c;无论是运行个大型的…...

Connext DDSPersistence Service持久性服务(2)

可选数据库组件及兼容性当Persistence Service配置为PERSISTENT模式时,您可以选择将主题数据存储在文件中还是存储在外部关系数据库中。 唯一支持的外部数据库是MySQL。 当PersistenceService在PERSISTENT模式下使用时,您可以将其配置为将DDS样本存储到关系数据库中,例如MyS…...

MongoDB

MongoDB 应用场景 ​ 在传统数据库&#xff08;Mysql&#xff09;&#xff0c;在数据操作的 **High performance 对数据库高并发读写的需求、Hugu Storage 对海量数据的高效率存储和访问的需求、High Scalability && High Availability 对数据库高扩展和高可用性的需…...

python 迭代器生成器

目录 一、可迭代对象 1.1 判断是否为可迭代对象 二、迭代器 2.1 判断对象是否是一个迭代器 2.2 手写一个迭代器 2.3 迭代器应用场景 三、生成器 3.1 生成器介绍 3.2 使用yield 关键字 生成器&#xff0c;来实现迭代器 3.3 生成器&#xff08;yield关键字&#xff09;…...

Iceberg基于Spark MergeInto语法实现数据的增量写入

SPARK SQL 基本语法 示例SQL如下 MERGE INTO target_table t USING source_table s ON s.id t.id //这里是JOIN的关联条件 WHEN MATCHED AND s.opType delete THEN DELETE // WHEN条件是对当前行进行打标的匹配条件 WHEN MATCHED AND s.opType update THEN…...

JavaScript Array(数组) 对象

JavaScript 中的 Array&#xff08;数组&#xff09;对象是一种用来存储一系列值的容器&#xff0c;它可以包含任意类型的数据&#xff0c;包括数字、字符串、对象等等。通过使用数组对象&#xff0c;我们可以轻松地组织和处理数据&#xff0c;以及进行各种操作&#xff0c;比如…...

Debian如何更换apt源

中科大 deb https://mirrors.ustc.edu.cn/debian/ stretch main non-free contrib deb https://mirrors.ustc.edu.cn/debian/ stretch-updates main non-free contrib deb https://mirrors.ustc.edu.cn/debian/ stretch-backports main non-free contrib deb-src https://mirr…...

Connext DDSPersistence Service持久性服务

DDS持久性服务,它保存了DDS数据样本,以便即使发布应用程序已经终止,也可以稍后将其发送到加入系统的订阅应用程序。 简介Persistence Service是一个Connext DDS应用程序,它将DDS数据样本保存到临时或永久存储中,因此即使发布应用程序已经终止,也可以稍后将其交付给加入系…...

自抗扰控制ADRC之微分器TD

目录 前言 1 全程快速微分器 1.1仿真分析 1.2仿真模型 1.3仿真结果 1.4结论 2 Levant微分器 2.1仿真分析 2.2仿真模型 2.3仿真结果 3.总结 前言 工程上信号的微分是难以得到的&#xff0c;所以本文采用微分器实现带有噪声的信号及其微分信号提取&#xff0c;从而实现…...

链表学习之复制含随机指针的链表

链表解题技巧 额外的数据结构&#xff08;哈希表&#xff09;&#xff1b;快慢指针&#xff1b;虚拟头节点&#xff1b; 复制含随机指针的链表 该链表节点的结构如下&#xff1a; class ListRandomNode { public:ListRandomNode() : val(0), next(nullptr), random(nullptr…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...