此文章属于ruoyi项目实战系列

ruoyi系统在前端主要通过权限字符包含与否来动态显示目录和按钮。为了防止通过http请求绕过权限限制,后端接口也需要进行相关权限设计。

@PreAuthorize使用

由于对@PreAuthorize原理还不够深入了解,所以此处只粗浅讲解在ruoyi项目是如何应用的。

在请求调用接口前,被@preAuthorize注解的接口需要首先通过验证。通过注解参数value()返回值truefalse来判断是否有权限。

public @interface PreAuthorize {
String value();
}

Ruoyi并没有使用原生的Spel表达式,而是使用了自定义的PermissionService类,通过其中自定义方法hasPermi(String Permission) 来进行权限判断。注解使用举例:@PreAuthorize("@ss.hasPermi('system:menu:list')")

public boolean hasPermi(String permission)
{
if (StringUtils.isEmpty(permission))//用注解就必须有permission值
{
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) ||
CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
return hasPermissions(loginUser.getPermissions(), permission); private boolean hasPermissions(Set<String> permissions, String permission)
{
return permissions.contains(ALL_PERMISSION) ||
permissions.contains(StringUtils.trim(permission)); //判断是否持有"所有权限”字符,或者持有该权限
}

接口权限校验流程

粗略用两个例子来讲解前端请求如何经过后端接口权限校验。

Login匿名请求

  1. Login请求路径是/login,在过滤器链中被AnnoymousAuthenticationFilter添加匿名authentication到Spring上下文里。由于/login请求在SecurityConfig.java里设置成匿名请求,所以可以成功到达SysLoginController

  2. 调用SysLoginService.login方法,关键的一行命令:

    Authentication authentication = authenticationManager
    .authenticate(new UsernamePasswordAuthenticationToken(username, password));

    authenticationManager.authenticate()是钩子方法,在AbstractUserDetailsAuthenticationProvider中实现,会根据传入的token类型来自动选择,此处UsernamePasswordAuthenticationToken将由DaoAuthenticationProvider来处理(不清楚的话可以前后打两个断点看调用栈)。

  3. DaoAuthenticationProvider中可以看到关键的一行:

    UserDetails loadedUser = this.getUserDetailsService()
    .loadUserByUsername(username);

    这会调用我们自定义实现的UserDetailsServiceImpl#loadUserByUsername方法(如流程图所示),获得user信息。至于为什么会使用自定义方法,因为在SecurityConfig.java中进行了配置

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }
  4. 生成token,然后返回。

已登录请求

已登录请求流程较简单,在流程图里的some filters里会通过自定义的JwtAuthenticationFilter,其中会通过token获得user信息,然后装入Spring的上下文,方便提取使用。

曾纠结踩坑的点

由于对SpringSecurity较陌生,虽然功能强大,但其复杂性也是大大提高,所以调试项目的同时翻看了很多入门博客文章,其中都不约而同的提到了UsernamePasswordAuthenticationFilter,可是我在实战项目中反复调试都没有看到这个过滤器的调用。

原因:Security配置文件需要添加httpSecurity.formLogin()启用表单登录才会使用该filter。查看项目使用的所有filter可以使用以下测试代码:


class RuoYiApplicationTest {
@Autowired
private FilterChainProxy filterChainProxy;
@Test
public void test() {
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
for(SecurityFilterChain sfc:filterChains){
for(Filter filter:sfc.getFilters()){
System.out.println(filter.getClass().getName());
}
}
}
}

ruoyi接口权限校验的更多相关文章

  1. 使用AOP+自定义注解完成spring boot的接口权限校验

    记使用AOP+自定义注解完成接口的权限校验,代码如下: pom文件添加所需依赖: 1 <dependency> 2 <groupId>org.aspectj</group ...

  2. SpringCloud(8)---zuul权限校验、接口限流

    zuul权限校验.接口限流 一.权限校验搭建 正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的 ...

  3. Apache shiro之权限校验流程

    从张开涛blog学习后整理:http://jinnianshilongnian.iteye.com/blog/2018398 图片原图比较大,建议将图片在新的选项卡打开后100%大小浏览 在权限校验中 ...

  4. 基于Spring Aop实现类似shiro的简单权限校验功能

    在我们的web开发过程中,经常需要用到功能权限校验,验证用户是否有某个角色或者权限,目前有很多框架,如Shiro Shiro有基于自定义登录界面的版本,也有基于CAS登录的版本,目前我们的系统是基于C ...

  5. SpringBoot系列 - 集成JWT实现接口权限认证

    会飞的污熊 2018-01-22 16173 阅读 spring jwt springboot RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authenticati ...

  6. 类Shiro权限校验框架的设计和实现(2)--对复杂权限表达式的支持

    前言: 我看了下shiro好像默认不支持复杂表达式的权限校验, 它需要开发者自己去做些功能扩展的工作. 针对这个问题, 同时也会为了弥补上一篇文章提到的支持复杂表示需求, 特地尝试写一下解决方法. 本 ...

  7. 类Shiro权限校验框架的设计和实现

    前言: 之前简单集成了springmvc和shiro用于后台管理平台的权限控制, 设计思路非常的优美, 而且编程确实非常的方便和简洁. 唯一的不足, 我觉得配置稍有些繁琐. 当时我有个小想法, 觉得可 ...

  8. 【JEECG技术文档】JEECG 接口权限开发及配置使用说明

    1.功能介绍   通过接口配置实现,对接口的访问权限控制和数据权限控制,接口时REST接口,接口权限认证机制使用Json web token (JWT) 接口权限调用流程: (1)通过接口用户的用户名 ...

  9. fastDFS shiro权限校验 redis FreeMark页面静态化

    FastDFS是一个轻量级分布式文件系统,   使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传.下载等服务   FastDFS服务端有两个角色:跟踪器(tracker)和存储节点( ...

随机推荐

  1. springboot jar包方式部署

    打好jar包后上传到 linux 执行命令 java -jar /root/vhr-web-0.0.1-SNAPSHOT.jar > /root/log.txt & 1.java -ja ...

  2. Unity中制作血条2.0

    ##1.血量显示 不必像之前那样添加Slider组件 直接创建Image 在添加Source Image之后,将Image Type 修改为Filled 通过修改Fill Mode就可以显示不同效果 ...

  3. vue3响应式模式设计原理

    vue3响应式模式设计原理 为什么要关系vue3的设计原理?了解vue3构建原理,将有助于开发者更快速上手Vue3:同时可以提高Vue调试技能,可以快速定位错误 1.vue3对比vue2 vue2的原 ...

  4. DjangoRestFramework框架三种分页功能的实现 - 在DjangoStarter项目模板中封装

    前言 继续Django后端开发系列文章.刚好遇到一个分页的需求,就记录一下. Django作为一个"全家桶"型的框架,本身啥都有,分页组件也是有的,但默认的分页组件没有对API开发 ...

  5. css 实现输入效果

    <template>   <h1>Pure CSS Typing animation.</h1> </template> <script> ...

  6. 2021.07.23 P2474 天平(差分约束)

    2021.07.23 P2474 天平(差分约束) [P2474 SCOI2008]天平 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 已知A,B和每两个点点权,求点权i, ...

  7. 接口测试实战| GET/POST 请求区别详解

    1.请求行的 method 不同:2.POST 可以附加 body,可以支持 form.json.xml.binary等各种数据格式:3.从行业通用规范的角度来说,无状态变化的建议使用 GET 请求, ...

  8. apparmor 源码分析

    这里不对apparmor做介绍,记录一下源码分析过程. 初始化 static int __init apparmor_init(void) -> security_add_hooks(appar ...

  9. JavaScript 数据结构与算法2(队列和双端队列)

    学习数据结构的 git 代码地址: https://gitee.com/zhangning187/js-data-structure-study 1.队列和双端队列 队列和栈非常类似,但是使用了与 后 ...

  10. 如何形象简单地理解java中只有值传递,而没有引用传递?

    首先,java中只有值传递,没有引用传递.可以说是"传递的引用(地址)",而不能说是"按引用传递". 按值传递意味着当将一个参数传递给一个函数时,函数接收的是原 ...