一、项目介绍
此项目是我之前发布的 项目实战2: 基于SpringBoot的购物商城系统 的改良版,之前的项目定位是购物商城,但是缺了很多模块,比如没有评论、购物车、收藏等购物商城的基本功能,顶多只算是一个增删改查的案例,其中对于一些技术的应用只是表面层次,例如 Redis,仅仅用来保存有期限的验证码。
本次改良将项目定位成一套超市账单后台管理系统,该管理系统的主要特点是可以动态地修改不同角色的权限。结合现实生活中,超市里不同身份的人具有不同的职责与权限。这次的项目更有专一性,虽然仍然缺少许多内容,但是可以作为 SpringBoot 增删改查的练手项目。
目前这个项目存在的不足(部分):
- 缺少日志管理
- 缺少导入、导出
- 缺少系统备份
- 存在一些业务逻辑的 BUG,但不影响基本使用
- …
采用技术栈:
用到的技术栈包括工具:
二、数据库设计
三、概要设计
确立对象,划分模块
首先确定系统的对象,然后分为不同的模块,根据对象的不同场景继续划分模块。
以最基本的系统用户出发,目前我设计的用户对象有以下 5 种:
1. 供应商管理员
用于管理超市中供应商的角色,主要是对于供应商信息进行管理,比如查询、添加、删除、修改供应商。
2. 销售员
根据商品来生成账单的角色,类似超市的收银员,比如查询商品、生成账单,修改账单状态。
3. 商品管理员
主要管理商品的角色,类似超市的货物管理员,负责管理每个商品的信息(位置、价格等),我们这里不涉及位置的管理,比如查询商品、修改商品信息、删除商品。
4. 网站管理员
具有网站所有权限的角色,是管理其他所有角色的关键角色,比如管理用户信息、用户角色、角色权限等。
5. 经理
查询系统的营收情况,后台统计报表信息,不用编辑任何信息,只需要查看可视化的图表,同时还可以查看用户信息,用户角色等。
综上,以上 5 种角色是结合之前的系统设计出来的,之前的项目确实太乱了,定位不清晰,现在这么简单的列出五种角色后,就清楚了许多,而且他们各司其职,我们可以更好的利用 Shrio 框架来进行权限管理。
四、详细设计
详细设计这一块不知道如何描述,我在写这个 “项目” 的时候,基本上就是想到什么写什么,只知道大概的流程,比如先从注册、登录的页面开始写起,写完页面,然后再写 Controller、Service、DAO。
现在发现,之前真的浪费太多时间了,页面能复制的就直接复制了,需要改的就改一下,目前接触了 Vue2,发现前端工程化的编码加上 组件库,非常容易上手而且写出来很清晰,像我在这个项目写的,尽管文件区分比较明确,但是里面的逻辑依然比较繁琐。
这里不一 一描述我这拙劣的设计方法了(太一般啦),就挑几个我自认为需要记录的内容说一下吧。
4.1 Shiro 授权与鉴权流程梳理
4.1.1 了解 Shiro
参考资料:Shiro 教程
Apache Shiro 是 Java 的一个安全框架。对比 Spring Security,功能没有那么强大,但是比较灵活。
既支持 普通的 Java 程序,又支持 Web开发的 JavaEE应用程序。
Shiro 解决的问题:
Shiro 架构图:
-
Subject:主体,代表了当前 “用户”,属于抽象概念,所有 Subject 都会绑定到 SecurityManager。
-
SecurityManager:安全管理器,管理所有的 Subject;是 Shiro 的核心,类似 SpringMVC 的 DispatcherServlet 。
-
Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),可以把 Realm 看成 DataSource,即数据源。
当用户登录时需进行授权,则需提前指定权限,然后再给指定的用户赋予相应的权限, Shiro 支持使用 ini 配置文件来授权,同样支持 DB 数据库来授权,这里则使用 MySQL 来存储 权限的内容,之后通过硬编码的方式,将 MySQL的权限注册到 Shiro 的会话中心。
4.1.2 Shiro 数据库设计
参考:RBAC模型 资料
Shiro 是用于授权和鉴权的框架,除此之外还需要使用 RBAC 模型来形成完整的一套支持权限管理的系统。 RBAC 即 Role-Base-Access-Controle ,基于角色的访问控制。
RBAC 模型分为四种,分别是 RBAC0、RBAC1、RBAC2 和 RBAC3, 安全等级依次提升。
目前了解 RBAC0 就行,只有更复杂的业务系统才需要更高权限模型。
RBAC0 是其他三个模型的基础,提出的是用户、角色、权限之间的关系,如下图:
根据这个模型来建立 五张数据表,如下图:
4.1.3 SpringBoot 整合 Shiro 思路
1. 引入 Shiro 依赖
这里使用 Spring 整合后的 Shiro 依赖 shiro-spring
,当引入依赖后经过一些配置,将 Shiro 相关的组件注入到 Spring 的容器中。
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.6.0</version>
</dependency>
2. 自定义 Realm
Shiro 的 Realm 层负责和数据库交互,定义认证与授权这两个过程,接下来是 Java 代码实现的流程:
package com.star.ms.admin.shiro;
import org.apache.shiro.realm.AuthorizingRealm;
// 实现 Realm 需要继承 Shiro 提供的 AuthorizingRealm 类
public class CustomRealm extends AuthorizingRealm {
// 从 Spring 容器获取 业务逻辑层中 用户、角色、权限的实现
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private PermService permService;
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
String principal = (String) principalCollection.getPrimaryPrincipal();
// 获取当前的用户信息
User user = userService.getByCode(principal);
if(user != null){
// 获取用户的角色
Role role = roleService.getByUserCode(user.getUsercode());
user.setRole(role);
// 赋予当前用户对应的角色信息(相同角色的权限是一致的)
if(role != null) {
info.addRole(role.getName