Java Web RBAC权限管理
- 前言
权限管理是在项目中经常要使用到的模块,有着极其重要的功能。比较出名的权限框架,分别为 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权限管理相关推荐
- java web简单权限管理设计
注:由于该项目比较老,所以没有采用maven管理,建议下载java后台通用权限管理系统(springboot)),对学习和使用会更有帮助. 最近在做一个网站类型项目,主要负责后台,ui框架选型为jqu ...
- java web项目 权限管理
方法一.SpringMVC整合Shiro (Shiro是强大的权限管理框架) http://www.360doc.com/content/14/0529/09/11298474_38191618 ...
- RBAC权限管理设计思想
RBAC权限管理设计 一.概述 二.权限模型 三.RBAC模型 什么是RBAC模型 基本模型RBAC0 角色分层模型RBAC1 角色限制模型RBAC2 统一模型RBAC3 基于RBAC的延展--用户组 ...
- nest-mysql:RBAC权限管理
文章问题导向 RBAC权限管理是什么?如何设计数据库?如何实现? 如果你都有了答案,可以忽略本文章,或去nest学习导图寻找更多答案 阅前必知 阅读此文,需要有一定的数据库知识 此文并非最佳实践,只能 ...
- RBAC权限管理设计
RBAC权限管理设计 一.RBAC组成 1. RBAC 2. RBAC组成 3. RBAC支持的安全原则 4. RBAC的优缺点 二.RBAC权限分配 1. RBAC的功能模块 2. RBAC权限分配 ...
- php rbac实现,php实现rbac权限管理
php实现rbac权限管理 介绍: RBAC(Role-Based Access Control)基于角色的权限管理方式. RBAC的最大特征就是将权限跟角色挂钩,用户又跟角色挂钩. 优点: ①管理维 ...
- rbac权限管理表mysql_RBAC权限管理数据库表小解
TP2.0版本就已经支持扩展RBAC权限管理,也有对应的demo,Rbac权限管理在Examples目录下面. RBAC扩展库核心文件则可以在ThinkPHP/Lib/ORG/Util下面找到,查看源 ...
- Vue3 实现 RBAC 权限管理
Vue3 实现 RBAC 权限管理 RBAC的基本概念 RBAC本质上就是一个授权的过程通过 用户 -> 角色---->资源 为啥要用RBAC 一个系统中用户是非常多的,对于不同的用户,展 ...
- kubernetes(k8s)之rbac权限管理详解
kubernetes(k8s)之rbac权限管理详解 RBAC简介 RBAC(Role-Based Access Control) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 ...
最新文章
- 03-NSPredicate谓词
- sql server和mysql分页查询_sql server和mysql中分别实现分页功能
- 谷歌将AutoML应用于Transformer架构,翻译结果飙升,已开源!
- 太任性!00 后少年买不到回国机票,因“泄愤”找黑客攻击系统,被判刑 4 年
- 软件测试技术学什么条件,软件测试从业者需要具备哪些技能
- 红黑树,看不懂你找我
- C# WinForm DataGridView单击选中一整行,只能单选
- 网络知识:内网、外网、宽带、带宽、流量、网速之间的联系?
- 11-11 又是一年光棍节!
- ROS中阶笔记(五):机器人感知—机器视觉
- Python实现人脸识别
- 数据结构课程设计(二)---算术表达式求值
- Linux快速查看OpenCV版本
- Sass学习(二)--混合器与继承
- 中病毒了文件夹变exe文件找到方法
- 华为微认证——鲲鹏处理器
- 用pl/sql解决芬兰数学家因卡拉设计的最难数独
- 从spark.default.parallelism参数来看Spark并行度、并行计算任务概念
- 【计算机网络-自顶向下方法第7版】学习笔记分享
- 题目:企业网络方案设计
热门文章
- DELL R720 新增内存条方法
- jQuery入门基本语法选择器
- BlackBerry Live 2013最大亮点:BBM今夏将登陆Android和iOS平台在今晚举办的“BlackBerry Live 2013”发布会上,黑莓除了推出新款BB10手机Q5外, 黑莓
- 如何快速有效的投诉上海移动
- 关于vray 5.2的使用(自研笔记)(二)
- java 界面实例,javagui界面实例
- 15-读乐嘉《本色》
- 研究生毕业一年有感 —— 写于2021年5月29号
- 使用DL模型预测台风/雷达回波/降水的datasets构建学习笔记
- 银行家算法例题讲解_银行家算法