当前位置:   article > 正文

EL-ADMIN的权限管理

EL-ADMIN的权限管理

参考官方文档:权限管理

https://el-admin.vip/guide/hdsc.html

一、官方文档介绍

本系统权限控制采用 RBAC 思想。简单地说,一个用户拥有若干角色,每一个角色拥有若干个菜单,菜单中存在菜单权限与按钮权限, 这样,就构造成“用户-角色-菜单” 的授权模型。在这种模型中,用户与角色、角色与菜单之间构成了多对多的关系,如下图

在这里插入图片描述

权限控制

本系统安全框架使用的是 Spring Security + Jwt Token, 访问后端接口需在请求头中携带token进行访问,请求头格式如下:

# Authorization: Bearer 登录时返回的token
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTU1ODk2NzY0OSwiaWF0IjoxNTU4OTQ2MDQ5f
  • 1
  • 2

数据交互

用户登录 -> 后端验证登录返回 token -> 前端带上token请求后端数据 -> 后端返回数据, 数据交互流程如下:

在这里插入图片描述

权限注解

Spring Security 提供了Spring EL表达式,允许我们在定义接口访问的方法上面添加注解,来控制访问权限,常用的 EL如下

表达式描述
hasRole([role])当前用户是否拥有指定角色。
hasAnyRole([role1,role2])多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。

下面的接口表示用户拥有adminmenu:edit权限中的任意一个就能能访问update方法, 如果方法不加@preAuthorize注解,意味着所有用户都需要带上有效的 token 后能访问 update 方法

@Log(description = "修改菜单")
@PutMapping(value = "/menus")
@PreAuthorize("hasAnyRole('admin','menu:edit')")
public ResponseEntity update(@Validated @RequestBody Menu resources){
    // 略
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

由于每个接口都需要给超级管理员放行,而使用 hasAnyRole('admin','user:list')每次都需要重复的添加 admin 权限,因此在新版本 (2.3) 中加入了自定义权限验证方式,在验证的时候默认给拥有admin权限的用户放行。

源码:

// eladmin-common -> me.zhengjie.config.ElPermissionConfig
@Service(value = "el")
public class ElPermissionConfig {

    public Boolean check(String ...permissions){
        // 获取当前用户的所有权限
        List<String> elPermissions = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
        // 判断当前用户的所有权限是否包含接口上定义的权限
        return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用方式:

@PreAuthorize("@el.check('user:list','user:add')") 
  • 1

接口放行

在我们使用的时候,有些接口是不需要验证权限的,这个时候就需要我们给接口放行,使用方式如下

1、使用注解方式

只需要在Controller的方法上加入该注解即可

@AnonymousAccess
  • 1

2、修改配置文件方式

eladmin-system -> modules -> security -> config -> SecurityConfig

TIP

使用 permitAll() 方法所有人都能访问,包括带上 token 访问

使用 anonymous() 所有人都能访问,但是带上 token 访问后会报错

// 关键代码,部分略
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            // 支付宝回调
            .antMatchers("/api/aliPay/return").anonymous()
            // 所有请求都需要认证
            .anyRequest().authenticated();
    httpSecurity
            .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

二、RBAC

RBAC是什么?

RBAC 是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
在这里插入图片描述

Demo

用户表

用户id用户名性别
1张三
2李四
3王五

用户-角色表

id用户id角色id
11{1,2,3}
22{2}
33{3}

角色表

角色id角色名称角色表角色level角色描述
1admin1管理员
2staff2职工
3visitor3游客

权限表

权限id权限内容
1admin
2user:del
3user:add
4user:edit

角色-授权表

id角色id权限id
11{1,2,3}
22{2,4}
33{3}

这个是标准的RBAC的权限设置思路,接口的安全由权限表直接控制,之后将权限赋予对应的角色,这样用户有什么角色就有什么接口权限。

怎么使用这种表的设计。
在这里插入图片描述
这三层就是表对应的关系。

代码实现(伪)

@Controller
@RequestMapping("/user")
public UserController{
	
	@PostMapping()
	@PreAuthorize("hasAnyRole('admin')")
	public void createUser(){
		// 拥有admin权限的角色才能使用	
	}
	
	@PutMapping()
	@PreAuthorize("hasAnyRole('admin','user:edit')")
	public void update(){
		// 拥有 admin 或者 user:edit 权限的角色才能使用	
	}
	
	@DeleteMapping()
	@PreAuthorize("hasAnyRole('user:del')")
	public void dataController(){
		// 拥有 user:del 权限的角色才能使用
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

通过上述图,如果用户发出接口请求,会从根据当前用户的角色寻找此角色的权限接口有哪些,最后自动判断后通过接口

所以不要再写根据当前用户角色判断业务逻辑的方式了。

1、权限赋予:
权限赋予是把当前用户的权限拉出来,然后分配的客服可以小于等于当前用户的权限。

2、权限加载:
正常的加载权限,当用户登录后,并且第一次使用权限判断的时候, Shiro 会去加载权限。

3、权限判断:
走正常用户权限判断,但是数据操作需要判断是不是当前归属的用户的数据,其实这个是属于业务层,就算你不是客服,也是需要判断。

4、禁用|启用:
禁用启用,也是正常的用户流程,添加到禁用列表里,如果被禁用,就无法操作任何内容。

三、eladmin中的权限管理

在这里插入图片描述
el-admin中将权限标识放在了permission字段

所谓的权限控制说白了,就是一个字符串,在前端 用户登录后会查到当前用户的所有权限标识符,进行crud操作的时候会去匹配,匹配到这个字符串,就是有权限,能操作,反之则不能。 在后端 访问接口的时候通过token 查询到当前用户的所有权限去匹配接口上的权限标识,进行判断。

接下来详细看议案源码中是怎么实现的吧

权限注解

前面已经介绍过,在登录后访问接口时会携带token进行识别

随便打开一个接口,

在这里插入图片描述
可以看到标红的注解@PreAuthorize("@el.check(‘user:add’)"),这是什么意思呢?在IDEA环境下,按住ctrl键点击@el.check,可以看到源代码如下:

/**
 * @author Zheng Jie
 */
@Service(value = "el")
public class ElPermissionConfig {

    public Boolean check(String ...permissions){
        // 获取当前用户的所有权限
        List<String> elPermissions = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
        // 判断当前用户的所有权限是否包含接口上定义的权限
        return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里的意思就是,用户的权限包含 admin 或 接口上的权限标识符 就返回true

界面如何添加权限

在这里插入图片描述
创建好权限后与角色绑定
在这里插入图片描述
保存后,即可在数据库中看到
在这里插入图片描述

前端对权限的判断

在这里插入图片描述
在这里插入图片描述

用户登录成功后,会查询到当前用户的所有信息(包括权限信息),同时这些信息也会存在token中,在前端操作中,会通过这些信息进行判断,访问后端接口则通过token

这就是 RBAC 的权限设计思想,并没有想象中那么复杂

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/367920
推荐阅读
相关标签
  

闽ICP备14008679号