ruoyi接口权限校验

虚幻大学 xuhss 169℃ 0评论

? 优质资源分享 ?

学习路线指引(点击解锁) 知识定位 人群定位
? Python实战微信订餐小程序 ? 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
?Python量化交易实战? 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

此文章属于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 permissions, String permission)  
{  
    return permissions.contains(ALL_PERMISSION) ||
     permissions.contains(StringUtils.trim(permission)); //判断是否持有"所有权限”字符,或者持有该权限 
}

接口权限校验流程

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

Login匿名请求

cecc7cb598c7f88cb19c34b68abfc033 - ruoyi接口权限校验

  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来处理(不清楚的话可以前后打两个断点看调用栈)。

  1. 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());  
}
  1. 生成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 filterChains = filterChainProxy.getFilterChains(); 
 for(SecurityFilterChain sfc:filterChains){ 
 for(Filter filter:sfc.getFilters()){ 
 System.out.println(filter.getClass().getName()); 
 } 
 } 
 } 
}

转载请注明:xuhss » ruoyi接口权限校验

喜欢 (0)

您必须 登录 才能发表评论!