文章目录

  • 一、项目介绍
  • 二、数据库设计
  • 三、概要设计
    • 确立对象,划分模块
  • 四、详细设计
    • 4.1 Shiro 授权与鉴权流程梳理
      • 4.1.1 了解 Shiro
      • 4.1.2 Shiro 数据库设计
      • 4.1.3 SpringBoot 整合 Shiro 思路
        • 1. 引入 Shiro 依赖
        • 2. 自定义 Realm
        • 3. 注入 Shiro 的组件到 IOC 容器中
        • 4. Shiro 的使用
    • 4.2 阿里 OSS 云存储服务
    • 4.3 页面设计
      • 1. 登录页面
      • 2. 注册页面
      • 3. 后台报表页面
      • 4. 后台用户管理页面
      • 5. 用户角色管理页面
      • 6. 供应商管理页面
      • 7. 商品管理页面
      • 8. 账单管理页面
      • 9. 角色权限管理页面
      • 10. 权限列表管理页面
      • 11. 个人信息页面
  • 五、代码获取

一、项目介绍


此项目是我之前发布的 项目实战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 容器获取 业务逻辑层中 用户、角色、权限的实现@Autowiredprivate UserService userService;@Autowiredprivate RoleService roleService;@Autowiredprivate PermService permService;// 授权@Overrideprotected 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());
//                 添加权限List<Perm> perms = permService.getByRoleId(role.getId());if(perms!=null && !CollectionUtils.isEmpty(perms)) {perms.forEach(perm -> {info.addStringPermission(perm.getUrl());});}}}return info;}// 认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException {// 获取身份信息String principal = (String) token.getPrincipal();// 调用业务层,获取数据库里对应的用户信息User user = userService.getByCode(principal);if(!ObjectUtils.isEmpty(user)){return new SimpleAuthenticationInfo(principal,user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName());}else return null;}
}

自定义 Realm 类里制定了 用户在注册登录时候的认证过程 doGetAuthenticationInfo,以及在登录后的授权过程 doGetAuthorizationInfo。

3. 注入 Shiro 的组件到 IOC 容器中

package com.star.ms.config;@Configuration
public class ShiroConfig {@AutowiredRoleService roleService;@AutowiredPermService permService;// 创建 Realm 对象@Beanpublic CustomRealm customerRealm(){CustomRealm realm = new CustomRealm();// 修改凭证校验匹配器HashedCredentialsMatcher hcm = new HashedCredentialsMatcher();hcm.setStoredCredentialsHexEncoded(true);// 设置加密算法为 MD5hcm.setHashAlgorithmName("MD5");// 设置散列次数hcm.setHashIterations(1024);realm.setCredentialsMatcher(hcm);return realm;}// 安全管理器@Bean(name="securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("customerRealm") Realm realm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(realm);return securityManager;}// 过滤链工厂@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();// 设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);Map<String, String> filterMap = new LinkedHashMap<>();// 获取所有权限信息 配置数据库的权限信息List<Perm> perms = permService.list();perms.forEach(perm ->{for (String p : perm.getUrl().split(",")) {filterMap.put(p, String.format("perms[%s]",p));}});// 配置公共权限 (游客的权限)filterMap.put("/user/login", "anon");filterMap.put("/user/verify", "anon");filterMap.put("/register/*", "anon");filterMap.put("/login.html", "anon");filterMap.put("/home.html", "anon");bean.setFilterChainDefinitionMap(filterMap);// 设置登录的请求bean.setLoginUrl("/login.html");// 未授权页面bean.setUnauthorizedUrl("/noauth");return bean;}// 整合 ShiroDialect: 用来整合 shiro thymeleaf@Beanpublic ShiroDialect getShiroDialect(){return new ShiroDialect();}// Shiro注解开发需要的Bean@Beanpublic AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(){return new AuthorizationAttributeSourceAdvisor();}
}

注入的 Bean 主要有 1)自定义的 Realm 对象;2)Shiro 安全管理器 ;3)Shiro 的 过滤链工厂 。

  • 自定义 Realm,负责指定 Shiro 进行认证和鉴权的一种策略。
  • Shiro 安全管理器,负责添加自定义的 Realm,在用户登录前后走自定义的认证与授权过程。
  • Shiro 过滤链工厂,负责指定有哪些权限的限制,包括设置公用的资源。

4. Shiro 的使用

在配置好 Shrio 的权限以及用户的认证和鉴权方式后,接下来就是关于 Shiro 的使用,以 UserService 中的登录为例

public User login(User user) {User loginUser = null;if(user.getUsercode()!=null && user.getPassword()!=null) {loginUser = userDAO.selectByCode(user.getUsercode());// 封装一个 TokenUsernamePasswordToken token = new UsernamePasswordToken(user.getUsercode(), user.getPassword(), false);// 获取主体Subject subject = SecurityUtils.getSubject();subject.login(token);// 验证成功后返回对象// 查询角色loginUser.setRole(roleService.getByUserCode(loginUser.getUsercode()));}return loginUser;
}

认证使用流程如下:

  1. 通过 SecurityUtils 对象获取到当前的 Subject
  2. 根据用户的账号和密码封装一个 Shiro 提供的 Token 类
  3. 调用 Subject 的 login方法,将 token 传入自定义Realm的认证方法,如果 login 登录失败的话就会抛出 Shiro 提供的几个异常,这里我没有捕获异常,就默认不会出现。

Shiro 鉴权的使用有许多,比如在 Controller 层:同样是通过 SecurityUtils 获取 Subject,然后调用 Subject 对象的 isPermmited 判断是否有某个权限。

@GetMapping("/admin/{type}")
public String toAdminUser(Model model, @PathVariable String type){<dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.1.0</version></dependency>

另一种就是使用经过 Thymeleaf 模板引擎渲染的 HTML,需要单独引入 thymeleaf-shiro的依赖

 <dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.1.0</version></dependency>

使用时:

<div xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">shiro:hasRole="管理员"><div>
<div>

至此, Shiro 的详细设计已完毕。

4.2 阿里 OSS 云存储服务

为了减轻服务器压力,对于管理系统的图片,我一致使用的是 阿里云的 OSS 云存储服务,首先得费用很低,一年10块左右,其次是更安全、更高效。

阿里云 OSS 官方地址:阿里云 OSS 服务

SpringBoot 整合 阿里云 OSS 可参考这篇文章:SpringBoot 整合 OSS

项目中用 OSS 的方法是先声明 OssService 接口,定义一些与OSS交互有关的方法。

package com.star.ms.common.service;import com.star.ms.common.entity.api.OssUploadResult;
import org.springframework.stereotype.Service;import java.util.List;@Service
public interface OssService {// 获取所有图片的路径public List<String[]> getDefaultHeadImgLink();// 上传文件public OssUploadResult upload(String userCode, String img64base);// 获取文件路径public String getUserImgPath(String userCode, String imgType);}

这些方法会用到 OSS 依赖提供的 OSS 对象,所以在实现这个接口前,需要声明 OSS 相关的 Bean 到 Spring 容器

package com.star.ms.common.api;import com.aliyun.oss.*;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;import java.util.LinkedList;
import java.util.List;@Configuration
public class OssApi {public static final String ENDPOINT = "OSS的域";public static final String ACCESS_KEY_ID = "OSS的验证ID";public static final String ACCESS_KEY_SECRET = "OSS的验证密钥";public static final String BUCKET_NAME = "OSS中Buncket块的名称";// 根据配置将 OSS 注入到 Spring 的 IoC 容器@Beanpublic OSS OSSClient(){return new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);}
}

4.3 页面设计

以下页面是我用 Bootstrap5 凑出来的,可能不太没美观,以简约为主。由于想着用 AJAX 请求数据,尽量做到前后端分离,结果在后面用到了 Boostrap5 的模态框,写了很多重复的杂冗的 JS 代码…

1. 登录页面

2. 注册页面

3. 后台报表页面

4. 后台用户管理页面

5. 用户角色管理页面

6. 供应商管理页面

7. 商品管理页面

8. 账单管理页面

9. 角色权限管理页面

10. 权限列表管理页面

11. 个人信息页面


五、代码获取

这个项目本来就没什么技术含量,所以我决定直接开源,希望能帮助到有需要的朋友吧,也希望自己将来有更好的技术水平来优化一下。

安全起见,我关闭了 OSS的可写功能,所以部署项目后的上传自定义图片功能将失效,过段时间我会考虑将 OSS 移除,采用本地存储,这样就可以一键部署成功了。

项目地址:Gitee

项目实战4: 基于 SpringBoot 的超市账单管理系统相关推荐

  1. 基于Vue和SpringBoot的超市账单管理系统的设计和实现

    作者主页:Designer 小郑 作者简介:Java全栈软件工程师一枚,来自浙江宁波,负责开发管理公司OA项目,专注软件前后端开发(Vue.SpringBoot和微信小程序).系统定制.远程技术指导. ...

  2. [嵌入式Linux项目实战开发]基于QT4.8的仓库管理系统实现功能【2019年给力项目】

    [嵌入式Linux项目实战开发]基于QT4.8的仓库管理系统实现功能[2019年给力项目] 支持导出 excel 表格 支持查看商品操作日志 支持高精度浮点运算 支持同一商品以不同价格入库 该软件已开 ...

  3. java超市收银项目答辩ppt_基于Java的超市货物管理系统的设计与实现毕业论文+开题报告+源码及数据库+答辩PPT+运行说明...

    基于Java的超市货物管理系统的设计与实现 摘要:在超市日常管理中,商品的进.销.存等决策以经验为主,缺乏实时分析功能,管理人员对及时传递资料的要求始终得不到满足.随着超市形态的高速发展,其经营管理也 ...

  4. 【项目实战】- 基于SpringBoot+WebScoket+Vue+ElementUI实现一个网页版地球聊天软件

    项目介绍 项目已开源gitee: https://gitee.com/gdones/gd-webchart 技术选型 后端:SpringBoot(WEB)+ JWT + MyBatis-plus +M ...

  5. 基于SSM的超市账单管理系统

    项目背景 在超市日常管理中,需要管理大量的商品进出,以及各种客户的订单和供应商的订单,如果按照以前手动方式记录,不仅耗时耗力,还容易丢失数据,造成经济方面的损失. 在计算机行业高速发展的今天,利用Ja ...

  6. 基于SSM的超市会员管理系统

    项目名称:基于SSM的超市会员管理系统(cshy_sys) 前端技术:H-ui.HTML.CSS.JS.JQuery等 后端技术:JSP.SSM框架 运行环境:Windows10以上.JDK1.8 数 ...

  7. 基于SpringBoot的医院门诊管理系统,高质量毕业论文范例-可直接参考使用,附源码和数据库脚本,项目导入运行视频教程,论文撰写教程

    1.项目技术栈 前端必学三个基础HTML.CSS.JS,基本每个B/S架构项目都要用到,基础中的基础.此外项目页面使用thymeleaf等前端框架技术. 后端使用Java主流的框架SpringBoot ...

  8. 基于SpringBoot的医院门诊管理系统,源码,数据库脚本,项目导入运行视频教程,论文撰写教程

    目录 项目技术栈 适合对象 适合课题 项目功能概述 毕业设计撰写视频教程 部分运行截图 项目技术栈 前端必学三个基础,前端"三剑客-"HTML.CSS.JS",基本每个B ...

  9. android中私有方法 继承,Android项目实战系列—基于博学谷(五)个人资料

    由于这个模块内容较多,篇幅较长,请耐心阅读. 个人资料模块分为两个部分 [x] [个人资料]() [x] [资料修改]() 一.个人资料 1.个人资料界面 (1).创建个人资料界面 在com.buxu ...

最新文章

  1. 简单探讨JavaScript 与 TypeScript之间的联系
  2. Apache启动报错
  3. 万字长文,一文读懂Linux的常规操作(墙裂建议收藏)
  4. ISE如何封装与使用IP —— 使用ngc文件与仅包含端口的v文件
  5. pandas:数据规范化方法与python实现
  6. ROS笔记(9) launch文件
  7. jquery 获取元素图片_【jQuery】获取图片真实宽高
  8. 系统维护好帮手—Starter
  9. python敏感词过滤替换_浅谈Python 敏感词过滤的实现
  10. multism中ui和uo应该怎么表示_multisim12中XBP1怎么使用
  11. 适配ofd签章SES_Signature
  12. xposed框架_把安卓手机开发到极致的框架xposed
  13. 盗火:硅谷、海豹突击队和疯狂科学家如何变革我们的工作和生活
  14. 电脑技巧:加装SSD固态硬盘注意事项,电脑速度超流畅
  15. 开关电源正负极两端加104电容的作用是什么?
  16. ImageMagick将多张图片拼接成一张图片_批量裁剪图片、拼接长图、添加水印不想打开ps,你可以试试这款软件...
  17. 把网站服务器调黑白,服务器安全狗怎么设置黑白名单?
  18. excel内容少却文件很大_(excel内容很少,文件却很大,怎么解决)excel表格数据少但是过大怎么办...
  19. 企业微信三方开发(五):扫码登录
  20. 用WinDbg分析电脑蓝屏文件

热门文章

  1. 提出一个问题:《纪念碑谷》
  2. 文档处理教程:使用Java拆分MS Word文档
  3. 史上最全NLP工具数据集下载汇总,不用积分就能下载
  4. 制作gif动态图片,使用哪款软件,经验分享
  5. 全球25米分辨率PALSAR镶嵌式和森林/非森林地图(FNF)。数据集介绍及下载
  6. 二维码还能防伪?这是什么新魔法……
  7. 罗斯蒙特流量计应用领域
  8. java 求导函数_在MATLAB中计算数值导数的最佳方法是什么?
  9. AD的常用快捷键——PCB部分
  10. 《查理·芒格的智慧:投资的格栅理论》读书笔记