• 前言

权限管理是在项目中经常要使用到的模块,有着极其重要的功能。比较出名的权限框架,分别为 Shiro 和 Spring Security,两者各有优缺,这次我们不用任何权限框架来实现 RBAC 权限管理。

  • RBAC 简介

RBAC (Role-Based Access Control) 基于角色的权限访问控制。
即用户拥有角色,角色拥有权限。具体关于 RBAC 的好处我就不再多说,如感兴趣请自行查询。

  • 数据库设计

共有五张表,分别为用户表、角色表、权限表、用户-角色关系表、角色-权限关系表。其中用户表于角色表是多对多的关系,角色表于权限表也是多对多关系。具体每个字段的含义请查看相应的注释。
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;


– Table structure for permission


DROP TABLE IF EXISTS permission;
CREATE TABLE permission (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ‘权限名称’,
description varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ‘权限描述表’,
PRIMARY KEY (id) USING BTREE
)
ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘权限表’ ROW_FORMAT = Dynamic;


– Table structure for role


DROP TABLE IF EXISTS role;
CREATE TABLE role (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ‘权限名称’,
description varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ‘权限描述’,
PRIMARY KEY (id) USING BTREE
)
ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘角色表’ ROW_FORMAT = Dynamic;


– Table structure for role_premission


DROP TABLE IF EXISTS role_premission;
CREATE TABLE role_premission (
role_id int(11) NULL DEFAULT NULL,
permission_id int(11) NULL DEFAULT NULL,
INDEX role_premission_uid_fk(role_id) USING BTREE,
INDEX role_premission_pid_fk(permission_id) USING BTREE,
CONSTRAINT role_premission_pid_fk FOREIGN KEY (permission_id) REFERENCES permission (id) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT role_premission_uid_fk FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;


– Table structure for user


DROP TABLE IF EXISTS user;
CREATE TABLE user (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ‘用户名’,
password varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ‘密码’,
PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘用户表’ ROW_FORMAT = Dynamic;


– Table structure for user_role


DROP TABLE IF EXISTS user_role;
CREATE TABLE user_role (
user_id int(11) NULL DEFAULT NULL,
role_id int(11) NULL DEFAULT NULL,
INDEX user_role_uid_fk(user_id) USING BTREE,
INDEX user_role_rid_fk(role_id) USING BTREE,
CONSTRAINT user_role_rid_fk FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT user_role_uid_fk FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘用户角色表’ ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

  • 环境配置

本次基于的环境是 Spring + SpringMVC + MyBatis,不过即使你不会这几个框架也无所谓,因为权限管理没有涉及到太多这些框架的特性,用普通的 Servlet + JDBC 同样也可以实现。

  • 实体类

首先需要创建三个与数据库对应的实体类

public class User {private Integer id;private String username;private String password;// getter setter 略
}public class Role {private Integer id;private String name;private String description;// getter setter 略
}public class Permission {private Integer id;private String name;private String description;// getter setter 略
}
  • DAO 数据操作层

      **UserDao**
    
public interface UserMapper {int insert(User record);User selectByPrimaryKey(Integer id);int updateByPrimaryKey(User record);List<User> selectALL();/*** 查询用户拥有的角色列表* @param id 用户 id* @return 角色列表*/List<Role> selectRolesByPrimaryKey(Integer id);/*** 删除用户所有角色* @param id 用户id* @return 删除成功的条数*/int deleteRoles(Integer id);/*** 为用户赋予角色* @param userId 用户 id* @param roleId 授予的角色 id* @return 插入成功的条数*/int insertUserRole(@Param("user_id") Integer userId, @Param("role_id") Integer roleId);/*** 根据用户名密码查询账号是否存在* @param username  用户名* @param password  密码* @return  查询到的账号*/User selectUserByUsernameAndPassword(@Param("username")String username,@Param("password")String password);
}

RoleDao

public interface RoleMapper {int insert(Role record);Role selectByPrimaryKey(Integer id);int updateByPrimaryKey(Role record);List<Role> selectAll();/*** 查询角色拥有的权限列表* @param id 角色 id* @return 权限列表*/List<Permission> selectPermissionsByPrimaryKey(Integer id);/*** 删除角色所有的权限* @param id 角色 id* @return 删除成功的条数*/int deletePermissions(Integer id);/*** 为角色添加一个权限* @param roleId 角色 id* @param permissionId 权限 id* @return 插入成功的条数*/int insertRolePermission(@Param("role_id")Integer roleId, @Param("permission_id") Integer permissionId);
}

PermissionDao

public interface PermissionMapper {int insert(Permission record);Permission selectByPrimaryKey(Integer id);int updateByPrimaryKey(Permission record);List<Permission> selectAll();
}

只需要一些简单的 SQL 操作

  • 用户管理

  • 用户添加

HTML 页面

<form action="addUser" method="post">用户名:<input type="text" name="username">密 码:<input type="password" name="password"><input type="submit" value="提交">
</form>

Controller

public String addUserSubmit(User user) {return userService.add(user) > 0 ? "success" : "error";
}

service 和 dao 略.

  • 用户登录
<form action="login" method="post">用户名 :<input type="text" name="username"><br>密  码:<input type="password" name="password"><br><input type="submit" value="登陆">
</form>

Controller

public String login(String username, String password, HttpSession httpSession) {User user = userService.selectUserByUsernameAndPassword(username, password);if (user != null) {httpSession.setAttribute("user", user);return "登陆成功";}return "登陆失败";
}

service 和 dao 略.

  • 查看用户列表
    HTML页面
<table border="1"><tr><td>用户名</td><td>密码</td><td>操作</td></tr><c:forEach items="${users}" var="user"><tr><td>${user.username}</td><td>${user.password}</td><td><a href="grantRoleView?id=${user.id}">赋予角色</a></td></tr></c:forEach>
</table>

Controller

public ModelAndView listUser() {return new ModelAndView("user.jsp").addObject("users", userService.getAllUser());
}

service 和 dao 略.

  • 为用户赋予角色
    为用户赋予角色需要先添加角色,请先看下面的添加角色后再来操作。
    HTML 页面:
<form action="grantRole"><table border="1"><tr><td>当前用户</td><td>${user.username}<input type="hidden" name="id" value="${user.id}"></td></tr><tr><td>已拥有角色</td><td><c:forEach items="${grantRole}" var="role"><span>${role.name}</span></c:forEach></td></tr><tr><td>所有角色</td><td><c:forEach items="${roles}" var="role"><input type="checkbox" name="roleId" value="${role.id}"> ${role.name}</c:forEach></td></tr><tr><td></td><td><input type="submit" value="提交"></td></tr></table>
</form>

Controller

public String grantRole(int id, int[] roleId) {userService.updateRoles(id, roleId);return "success";
}

Service

public void updateRoles(Integer id, int[] roleIds) {userMapper.deleteRoles(id);if (roleIds != null) {for (int roleId : roleIds) {userMapper.insertUserRole(id, roleId);}}
}

其实这里的修改授权角色只是将原来它拥有的所有角色删除,再分配给它提交的所有角色。

  • 角色管理
  • 添加角色

HTML 页面:

<form action="addRole" method="post">角色名称:<input type="text" name="name">角色描述:<input type="text" name="description"><input type="submit" value="提交">
</form>

Controller

public String addRole(Role role) {return roleService.add(role) > 0 ? "success" : "error";
}

service 和 dao 略.

  • 角色列表
  • HTML 页面:
<table border="1"><tr><td>角色名称</td><td>角色描述</td><td>操作</td></tr><c:forEach items="${roles}" var="role"><tr><td>${role.name}</td><td>${role.description}</td><td><a href="grantPermissionView?id=${role.id}">赋予权限</a></td></tr></c:forEach>
</table>

Controller

public ModelAndView listRole() {return new ModelAndView("role.jsp").addObject("roles", roleService.getAll());
}

service 和 dao 略.

- 为角色赋予权限

- HTML 页面:

<form action="grantPermission"><table border="1"><tr><td>当前角色</td><td>${role.name}<input type="hidden" name="id" value="${role.id}"></td></tr><tr><td>已拥有权限</td><td><c:forEach items="${grantPermission}" var="permission"><span>${permission.name}</span></c:forEach></td></tr><tr><td>所有权限</td><td><c:forEach items="${permissions}" var="permission"><input type="checkbox" name="premissionId" value="${permission.id}"> ${permission.name}</c:forEach></td></tr><tr><td></td><td><input type="submit" value="提交"></td></tr></table>
</form>

Controller

public String grantPermission(int id, int[] premissionId) {roleService.updatePermission(id, premissionId);return "success";
}

Service:

public void updatePermission(Integer roleId, int[] permissionsIds) {roleMapper.deletePermissions(roleId);if (permissionsIds != null) {for (int permissionId : permissionsIds) {roleMapper.insertRolePermission(roleId, permissionId);}}
}

这里的为角色赋予权限同样也是先删除角色所拥有的权限,再添加表单提交的所有权限。

- 权限管理
- 添加权限

HTML 页面:

<form action="addPermission" method="post">权限名称:<input type="text" name="name">权限描述:<input type="text" name="description"><input type="submit" value="提交">
</form>

Controller:

public String add(Permission permission) {return permissionService.add(permission) > 0 ? "success" : "error";
}

service 和 dao 略.

  • 权限列表
  • HTML 页面:

<form action="addPermission" method="post">权限名称:<input type="text" name="name">权限描述:<input type="text" name="description"><input type="submit" value="提交">
</form>

Controller:

public String add(Permission permission) {return permissionService.add(permission) > 0 ? "success" : "error";
}

service 和 dao 略.

  • 权限拦截

既然已经分配好用户,角色以及权限之间的关系了,那么我们就可以设置一些需要权限才能访问的资源了。

我设置了 5 个 url, 并标注了需要何权限或何角色才可访问:
/api/add # add 权限
/api/delete # delete 权限
/api/get # get 权限
/api/employee # employee 角色
/api/boss # boos 角色
我们可以用拦截器来拦截 /api/* 下的所有请求,那么如何区分不同请求分别需要什么权限呢?

这里我参考了 Shiro 的设计,即采用注解的方式,在相应的方法上用 @RequiredRole 和 @RequiredPremission 来标注相应的请求需要某个角色或某个权限才可访问。

@RestController
@RequestMapping("/api")
public class APIController {@RequiredPermission("add")@RequestMapping("/add")public String add() {return "添加数据成功";}@RequiredPermission("delete")@RequestMapping("/delete")public String delete() {return "删除数据成功";}@RequiredPermission("get")@RequestMapping("/get")public String select() {return "查询数据成功";}@RequiredRole("boss")@RequestMapping("/boss")public String boss() {return "此数据为 Boss 专用数据, 你是 boss, 你可以查看";}@RequiredRole("employee")@RequestMapping("/employee")public String employee() {return "此数据为员工专用数据, 你是员工, 可以查看";}
}

拦截器获取拦截的方法上的注解即可得知需要什么权限,以便来进行相应的判断,Spring 拦截器:

public class PermissionHandlerInterceptor implements HandlerInterceptor {@Resourceprivate UserService userService;@Resourceprivate RoleService roleService;@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {response.setHeader("Content-type", "text/html;charset=UTF-8");Method method = ((HandlerMethod)handler).getMethod();RequiredRole requiredRole = method.getAnnotation(RequiredRole.class);RequiredPermission requiredPermission = method.getAnnotation(RequiredPermission.class);User user = (User) request.getSession().getAttribute("user");if (user == null) {response.getWriter().write("未登录");return false;}List<Role> userRoles = userService.getUserRoles(user.getId());if (requiredRole != null) {for (Role role : userRoles) {if (role.getName().equals(requiredRole.value())) {return true;}}}if (requiredPermission != null) {for (Role role : userRoles) {List<Permission> permissions = roleService.getPermissions(role.getId());for (Permission persission : permissions) {if (requiredPermission.value().equals(persission.getName())) {return true;}}}}response.getWriter().println("权限不足");return false;}
}

总结:
RBAC基本实现就这些

Java Web RBAC权限管理相关推荐

  1. java web简单权限管理设计

    注:由于该项目比较老,所以没有采用maven管理,建议下载java后台通用权限管理系统(springboot)),对学习和使用会更有帮助. 最近在做一个网站类型项目,主要负责后台,ui框架选型为jqu ...

  2. java web项目 权限管理

     方法一.SpringMVC整合Shiro (Shiro是强大的权限管理框架) http://www.360doc.com/content/14/0529/09/11298474_38191618 ...

  3. RBAC权限管理设计思想

    RBAC权限管理设计 一.概述 二.权限模型 三.RBAC模型 什么是RBAC模型 基本模型RBAC0 角色分层模型RBAC1 角色限制模型RBAC2 统一模型RBAC3 基于RBAC的延展--用户组 ...

  4. nest-mysql:RBAC权限管理

    文章问题导向 RBAC权限管理是什么?如何设计数据库?如何实现? 如果你都有了答案,可以忽略本文章,或去nest学习导图寻找更多答案 阅前必知 阅读此文,需要有一定的数据库知识 此文并非最佳实践,只能 ...

  5. RBAC权限管理设计

    RBAC权限管理设计 一.RBAC组成 1. RBAC 2. RBAC组成 3. RBAC支持的安全原则 4. RBAC的优缺点 二.RBAC权限分配 1. RBAC的功能模块 2. RBAC权限分配 ...

  6. php rbac实现,php实现rbac权限管理

    php实现rbac权限管理 介绍: RBAC(Role-Based Access Control)基于角色的权限管理方式. RBAC的最大特征就是将权限跟角色挂钩,用户又跟角色挂钩. 优点: ①管理维 ...

  7. rbac权限管理表mysql_RBAC权限管理数据库表小解

    TP2.0版本就已经支持扩展RBAC权限管理,也有对应的demo,Rbac权限管理在Examples目录下面. RBAC扩展库核心文件则可以在ThinkPHP/Lib/ORG/Util下面找到,查看源 ...

  8. Vue3 实现 RBAC 权限管理

    Vue3 实现 RBAC 权限管理 RBAC的基本概念 RBAC本质上就是一个授权的过程通过 用户 -> 角色---->资源 为啥要用RBAC 一个系统中用户是非常多的,对于不同的用户,展 ...

  9. kubernetes(k8s)之rbac权限管理详解

    kubernetes(k8s)之rbac权限管理详解 RBAC简介 RBAC(Role-Based Access Control) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 ...

最新文章

  1. 03-NSPredicate谓词
  2. sql server和mysql分页查询_sql server和mysql中分别实现分页功能
  3. 谷歌将AutoML应用于Transformer架构,翻译结果飙升,已开源!
  4. 太任性!00 后少年买不到回国机票,因“泄愤”找黑客攻击系统,被判刑 4 年
  5. 软件测试技术学什么条件,软件测试从业者需要具备哪些技能
  6. 红黑树,看不懂你找我
  7. C# WinForm DataGridView单击选中一整行,只能单选
  8. 网络知识:内网、外网、宽带、带宽、流量、网速之间的联系?
  9. 11-11 又是一年光棍节!
  10. ROS中阶笔记(五):机器人感知—机器视觉
  11. Python实现人脸识别
  12. 数据结构课程设计(二)---算术表达式求值
  13. Linux快速查看OpenCV版本
  14. Sass学习(二)--混合器与继承
  15. 中病毒了文件夹变exe文件找到方法
  16. 华为微认证——鲲鹏处理器
  17. 用pl/sql解决芬兰数学家因卡拉设计的最难数独
  18. 从spark.default.parallelism参数来看Spark并行度、并行计算任务概念
  19. 【计算机网络-自顶向下方法第7版】学习笔记分享
  20. 题目:企业网络方案设计

热门文章

  1. DELL R720 新增内存条方法
  2. jQuery入门基本语法选择器
  3. BlackBerry Live 2013最大亮点:BBM今夏将登陆Android和iOS平台在今晚举办的“BlackBerry Live 2013”发布会上,黑莓除了推出新款BB10手机Q5外, 黑莓
  4. 如何快速有效的投诉上海移动
  5. 关于vray 5.2的使用(自研笔记)(二)
  6. java 界面实例,javagui界面实例
  7. 15-读乐嘉《本色》
  8. 研究生毕业一年有感 —— 写于2021年5月29号
  9. 使用DL模型预测台风/雷达回波/降水的datasets构建学习笔记
  10. 银行家算法例题讲解_银行家算法