当前位置:   article > 正文

基于数据库的RBAC数据模型的权限控制_rbac权限管理 数据库 查询

rbac权限管理 数据库 查询

我们开发一个系统,必然面临权限控制的问题,不同的用户具有不同的访问、操作、数据权限。形成理论的权限控制模型有:自主访问控制(DAC: Discretionary Access Control)、强制访问控制(MAC: Mandatory Access Control)、基于属性的权限验证(ABAC: Attribute-Based Access
Control)等。最常被开发者使用也是相对易用、通用的就是RBAC权限模型(Role-Based Access
Control)

1、RBAC权限模型简介

RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制。模型中有几个关键的术语:

  • 用户:系统接口及访问的操作者
  • 权限:能够访问某接口或者做某操作的授权资格
  • 角色:具有一类相同操作权限的总称 

RBAC权限模型核心授权逻辑如下:

  • 某用户是什么角色?
  • 某角色具有什么权限?
  • 通过角色对应的权限推导出用户的权限 

2、RBAC的演化进程

2.1、用户与权限直接关联

想到权限控制,人们最先想到的一定是用户与权限直接关联的模式,简单地说就是:某个用户具有某些权限。如图: 

  • 张三具有所有权限他可能是一个超级管理员.
  • 李四,王五 具有添加商品和审核商品的权限有可能是一个普通业务员 

这种模型能够清晰的表达用户与权限之间的关系,足够简单。但同时也存在问题:

  • 现在用户是张三、李四,王五以后随着人员增加,每一个用户都需要重新授权
  • 操作人员的他的权限发生变更后,需要对每个一个用户重新授予新的权限 

2.2、用户与角色关联

这样只需要维护角色和权限之间的关系就可以了. 如果业务员的权限发生变更, 只需要变动业务员角色和权限之前的关系进行维护就可以了. 用户和权限就分离开来了. 如下图 

3、基于RBAC设计权限表结构

  • 一个用户有一个或多个角色
  • 一个角色包含多个用户
  • 一个角色有多种权限
  • 一个权限属于多个角色 

4、基于Spring Security 实现RBAC权限管理

4.1、动态查询数据库中用户对应的权限

  1. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2. import com.lagou.domain.Permission;
  3. import org.apache.ibatis.annotations.Select;
  4. import java.util.List;
  5. public interface PermissionMapper extends BaseMapper<Permission> {
  6. /**
  7. * 根据用户ID查询权限
  8. *
  9. * @param id
  10. * @return
  11. */
  12. @Select("SELECT p.* FROM t_permission p,t_role_permission rp,t_role r,t_user_role ur,t_user u " +
  13. "WHERE p.id = rp.PID AND rp.RID = r.id AND r.id = ur.RID AND ur.UID = u.id AND u.id =#{id}")
  14. List<Permission> findByUserId(Integer id);
  15. }

4.2、给登录用户授权 

这个是在实现UserDetailsService接口,在重写的loadUserByUsername的方法中

  1. Collection<GrantedAuthority> authorities = new ArrayList<>(); // 权限的集合,先声明一个权限集合, 因为构造方法里面不能传入null
  2. // 基于数据库查询用户对应的权限
  3. List<Permission> permissionList = permissionService.findByUserId(user.getId());
  4. for (Permission permission : permissionList) {
  5. // 授权
  6. authorities.add(new SimpleGrantedAuthority(permission.getPermissionTag()));
  7. }

4.3、设置访问权限

这个是在我们自定义类SecurityConfig继承了WebSecurityConfigurerAdapter接口,在其重写方法中设置,void configure(HttpSecurity http)

  1. // 查询数据库所有权限列表
  2. List<Permission> list = permissionService.list();
  3. for (Permission permission : list) {
  4. http.authorizeRequests().antMatchers(permission.getPermissionUrl())
  5. // 添加请求权限
  6. .hasAuthority(permission.getPermissionTag());
  7. }

之所以使用hasAuthority而不是使用hasRole是因为hasRole会在权限的前面加上"ROLE_".

5、基于页面端标签的权限控制

在jsp页面或者thymeleaf模板页面中我们可以使用spring security提供的权限标签来进行权限控制.要想使用thymeleaf为SpringSecurity提供的标签属性,首先需要引入thymeleaf-extras-springsecurity依赖支持。

5.1、在pom 文件中的引入springsecurity的标签依赖thymeleaf-extras-springsecurity5。

  1. <!--添加thymeleaf为SpringSecurity提供的标签依赖 -->
  2. <dependency>
  3. <groupId>org.thymeleaf.extras</groupId>
  4. <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  5. <version>3.0.4.RELEASE</version>
  6. </dependency>

5.2、在html文件里面申明使用

  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org"
  3. xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

5.3、常用SpringSecurity的标签属性介绍

判断用户是否已经登陆认证,引号内的参数必须是isAuthenticated()。
sec:authorize="isAuthenticated()"

获得当前用户的用户名,引号内的参数必须是name。
sec:authentication=“name”


判断当前用户是否拥有指定的权限。引号内的参数为权限的名称。
sec:authorize=“hasRole(‘role’)”

5.4、SpringSecurity标签的使用

  1. <div class="leftnav">
  2. <div class="leftnav-title">
  3. <div sec:authorize="isAuthenticated()"> <!--有权限时,为true,则会显示-->
  4. <span sec:authentication="name"></span>
  5. <img src="images/y.jpg" class="radius-circle rotate-hover" height="50" alt=""/>
  6. </div>
  7. </div>
  8. <div sec:authorize="hasAuthority('user:findAll')"> <!--有权限时,为true,则会显示-->
  9. <h2><span class="icon-user"></span>系统管理</h2>
  10. <ul style="display:block">
  11. <li><a href="/user/findAll" target="right"><span class="icon-caretright"></span>用户管理</a></li>
  12. <li><a href="javascript:void(0)" onclick="toCors()" target="right">
  13. <span class="icon-caret-right"></span>跨域测试</a></li>
  14. </ul>
  15. </div>
  16. <div sec:authorize="hasAuthority('product:findAll')"> <!--有权限时,为true,则会显示-->
  17. <h2><span class="icon-pencil-square-o"></span>数据管理</h2>
  18. <ul>
  19. <li><a href="/product/findAll" target="right"><span class="iconcaret-right"></span>商品管理</a></li>
  20. </ul>
  21. </div>
  22. </div>

6、记录bug

当我们开启CSRF防护后,我们点击项目中的登录按钮,会报404错误,这是因为logout登出功能的方法必须为post请求,并且我们还要携带

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>这里面的参数。这样才能登出成功,而不会报错。

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

闽ICP备14008679号