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

SpringSecurity实战入门——授权

权限系统的作用

例如一个学校图书馆的管理系统,如果是普通学生登录就能看到借书还书相关的功能,不可能让他看到并且去使用添加书籍信息,删除书籍信息等功能。但是如果是一个图书馆管理员的账号登录了,应该就能看到并使用添加书籍信息,删除书籍信息等功能。

总结起来就是不同的用户可以使用不同的功能。这就是权限系统要去实现的效果。

我们不能只依赖前端去判断用户的权限来选择显示哪些菜单哪些按钮。因为如果只是这样,如果有人知道了对应功能的接口地址就可以不通过前端,直接去发送请求来实现相关功能操作。

所以我们还需要在后台进行用户权限的判断,判断当前用户是否有相应的权限,必须具有所需权限才能进行相应的操作。


授权基本流程

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

所以我们在项目中只需要把当前登录用户的权限信息也存入Authentication。

然后设置我们的资源所需要的权限即可。


授权实现

限制访问资源所需权限

SpringSecurity为我们提供了基于注解的权限控制方案,这也是我们项目中主要采用的方式。我们可以使用注解去指定访问对应的资源所需的权限。

但是要使用它我们需要先开启相关配置

@EnableGlobalMethodSecurity(prePostEnabled = true)

然后就可以使用对应的注解。@PreAuthorize

@RestController
@RequestMapping("/book")
public class BookController {@GetMapping("/list")@PreAuthorize("hasAuthority('sys:book:list')")public String list() {return "book-list";}@GetMapping("/delete")@PreAuthorize("hasAuthority('sys:book:delete')")public String delete() {return "book-delete";}}

封装权限信息

我们前面在写UserDetailsServiceImpl的时候说过,在查询出用户后还要获取对应的权限信息,封装到UserDetails中返回。

我们先直接把权限信息写死封装到UserDetails中进行测试。

我们之前定义了UserDetails的实现类LoginUser,想要让其能封装权限信息就要对其进行修改。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {private User user;//存储权限信息private List<String> permissions;//存储SpringSecurity所需要的权限信息的集合@JSONField(serialize = false)private List<GrantedAuthority> authorities;public LoginUser(User user,List<String> permissions) {this.user = user;this.permissions = permissions;}@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;}
}

LoginUser修改完后我们就可以在UserDetailsServiceImpl中去把权限信息封装到LoginUser中了。我们写死权限进行测试,后面我们再从数据库中查询权限信息。

@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Resourceprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//根据用户名查询用户信息LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.eq(User::getUserName,username);User user = userMapper.selectOne(wrapper);//如果查询不到数据就通过抛出异常来给出提示if(Objects.isNull(user)){throw new RuntimeException("用户名或密码错误");}//TODO 根据用户查询权限信息 添加到LoginUser中List<String> list = new ArrayList<>(Arrays.asList("sys:book:list"));//封装成UserDetails对象返回return new LoginUser(user,list);}
}

我们在过滤器层面也需要将权限添加进去

<

相关文章:

  • 【实战】Spring Cloud Stream 3.1+整合Kafka
  • Python学习路线
  • vue3父组件获取子组件的实例对象
  • Ollama部署大模型并安装WebUi
  • 抽象类和接口有什么区别?
  • reidis的内存回收和内存淘汰策略
  • Android C++系列:C++最佳实践2抽象类
  • Spring Boot 增删改查(mybatis-plus)
  • MSPM0G3507——PWM
  • Elasticsearch Range 查询:范围搜索
  • ARM32常见指令
  • JAVA学习笔记DAY11——Java 与 Spring框架发展
  • Scala 中的匿名函数
  • 探索数据结构:集合、线性结构、树状结构和图形结构
  • 一文搞懂Linux信号【下】
  • 深入了解以太坊
  • JAVA SE 6 GC调优笔记
  • JavaScript 基本功--面试宝典
  • javascript从右向左截取指定位数字符的3种方法
  • JavaScript设计模式之工厂模式
  • Redux 中间件分析
  • SOFAMosn配置模型
  • spring学习第二天
  • supervisor 永不挂掉的进程 安装以及使用
  • 编写符合Python风格的对象
  • 技术发展面试
  • 简单基于spring的redis配置(单机和集群模式)
  • 老板让我十分钟上手nx-admin
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 算法-图和图算法
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 王永庆:技术创新改变教育未来
  •  一套莫尔斯电报听写、翻译系统
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • #define、const、typedef的差别
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (HAL库版)freeRTOS移植STMF103
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (二)windows配置JDK环境
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (强烈推荐)移动端音视频从零到上手(下)
  • (十三)MipMap
  • (五)Python 垃圾回收机制
  • (一)基于IDEA的JAVA基础12
  • (转)Linq学习笔记
  • .mysql secret在哪_MYSQL基本操作(上)
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .Net Core与存储过程(一)
  • .Net 垃圾回收机制原理(二)
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .Net7 环境安装配置
  • .net经典笔试题
  • @ConfigurationProperties注解对数据的自动封装
  • @RestControllerAdvice异常统一处理类失效原因