EL-ADMIN的权限管理

开源框架EL—ADMIN的权限管理的探究

  • 一、官方文档介绍
      • 权限控制
      • 数据交互
      • 权限注解
      • 接口放行
  • 二、RBAC
      • RBAC是什么?
      • Demo
  • 三、eladmin中的权限管理
    • 权限注解
    • 界面如何添加权限
    • 前端对权限的判断

参考官方文档:权限管理

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

一、官方文档介绍

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

权限控制

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

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

数据交互

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

EL-ADMIN的权限管理_第1张图片

权限注解

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){
    // 略
}

由于每个接口都需要给超级管理员放行,而使用 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);
    }
}

使用方式:

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

接口放行

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

1、使用注解方式

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

@AnonymousAccess

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);
}

二、RBAC

RBAC是什么?

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

Demo

用户表

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

用户-角色表

id 用户id 角色id
1 1 {1,2,3}
2 2 {2}
3 3 {3}

角色表

角色id 角色名称 角色表角色level 角色描述
1 admin 1 管理员
2 staff 2 职工
3 visitor 3 游客

权限表

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

角色-授权表

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

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

怎么使用这种表的设计。
EL-ADMIN的权限管理_第3张图片
这三层就是表对应的关系。

代码实现(伪)

@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、权限加载:
正常的加载权限,当用户登录后,并且第一次使用权限判断的时候, Shiro 会去加载权限。

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

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

三、eladmin中的权限管理

EL-ADMIN的权限管理_第4张图片
el-admin中将权限标识放在了permission字段

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

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

权限注解

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

随便打开一个接口,

EL-ADMIN的权限管理_第5张图片
可以看到标红的注解@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);
    }
}

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

界面如何添加权限

EL-ADMIN的权限管理_第6张图片
创建好权限后与角色绑定
EL-ADMIN的权限管理_第7张图片
保存后,即可在数据库中看到
EL-ADMIN的权限管理_第8张图片

前端对权限的判断

EL-ADMIN的权限管理_第9张图片
EL-ADMIN的权限管理_第10张图片

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

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

你可能感兴趣的:(RBAC,权限管理,eladmin)