APP下载

基于Spring Security的权限管理系统的设计与实现

2024-01-14苏兵

电脑与电信 2023年9期
关键词:菜单按钮分配

苏兵

(广东培正学院数据科学与计算机学院,广东 广州 510830)

1 引言

计算机技术日新月异,为了对特定的网络资源进行有效的保护,需要对任何投入运营的信息系统增加更高的安全模块,如身份验证、授权和加密方式等,从而防止数据泄露等问题[1]。在未使用安全框架之前,开发者需要手动地处理每个资源的访问控制,然而,针对不同的开发项目,又往往需要做出不同的处理,使得整个工程操作起来非常繁琐且低效率,进而引起更多额外的开销,导致延缓开发周期,增加开发成本。使用Spring Security与JWT,开发者可通过配置的方式实现对特定资源的访问限制,用户信息在各方传输时,通过JWT对数据加密后形成token,用来进行用户认证,确保用户的合法性[2-3]。该信息安全解决方案开发更加高效,且复用性高、维护开本低,深受国内外知名互联网公司青睐。

2 系统的整体设计

该权限管理系统有三类服务器:Web 服务器、数据库服务器和缓存服务器,客户端为PC 端和移动端,如图1 所示。Web 服务器后端采用微服务架构,关键技术为Spring Boot、MyBatis-plus、Spring Security 和JWT,缓存服务器采用Redis 高速缓存技术,数据库服务器采用关系型数据库MySQL,前端采用Vue.js和Element-Plus等技术。

图1 系统的整体设计

本文论述的重点是在Web服务器中应用Spring Security的功能,从而更好地保护Web 服务器的资源,以免被非法访问或攻击。基于对保护命令方式或反应式应用程序的有效支持,Spring Security可以作为一种提供身份验证、授权及防范攻击的功能性框架,更是作为保护基于Spring所开发应用程序的一种常用标准[4]。通过对Spring Security 的规范应用,进而使开发者更自如地实现对安全功能的标准集成,例如:对用户角色的权限管理,以此达到保护应用程序免遭严重攻击和非法访问的目的。下面对Web服务器中的Spring-Security安全组件进行分析:

(1)AuthenticationManager:负责认证管理,解析用户登录信息(封装在Authentication),读取用户、角色、权限信息进行认证,认证结果被回填到Authentication,保存在Securi-tyContext。

(2)AccessDecisionManager:负责授权投票表决,汇总投票器的结果,实现一票通过(默认)、多票通过、一票否决策略。

(3)SecurityInterceptor:负责权限拦截,包括Web URL拦截和方法调用拦截。通过ConfigAttributes 获取资源的描述信息,借助于AccessDecisionManager进行授权拦截。

(4)SecurityContext:安全上下文,保存认证结果。提供了全局上下文、线程继承上下文、线程独立上下文(默认)三种策略。

(5)Authentication:认证信息,保存用户的身份标示、权限列表、证书、认证通过标记等信息。

(6)SecuredResource:被安全管控的资源,如Web URL、用户、角色、自定义领域对象等。

(7)ConfigAttributes:资源属性配置,描述安全管控资源的信息,为SecurityInterceptor提供拦截逻辑的输入。

JSON Web Token(JWT)是一个开放式的标准(RFC 7519),其定义了一种紧凑且自包含的方式,用于作为JSON对象在各程序之间安全可靠地传输信息,该信息因经过数字签名,故可实现有效验证与事物的可信任性[5]。本系统采用JWT技术对用户信息进行加密处理,提高数据的安全性。为了实现前后端分离的设计模式,系统的前端在node.js运行环境下开发,后端则采用主流微服务架构。当用户通过客户端登录系统时,系统将会自动启动Spring Security 对用户的身份进行认证,当身份认证成功后,再通过JWT对用户加密后形成token,用户请求其他资源时只需携带token 即可,后端会通过token来识别用户身份。

3 基于角色的权限管理设计

本系统的数据库设计采用基于角色的访问控制模型(RBAC),在微服务架构下应用MyBatis-plus 框架嵌入到Spring Security 安全框架中,通过这种方式可以将用户关联角色,角色关联权限,从而间接地实现赋予用户相应的权限。如图2 所示,本系统的RBAC 模块由三部分组成:用户管理、角色管理和权限管理。

图2 RBAC模块功能

针对RBAC 模块功能,本系统数据库需设计5 张表:用户表、角色表、菜单表、用户角色中间表和角色菜单中间表。如图3 所示,用户表主要用于存储用户身份信息;角色表主要用于存储用户的角色信息;菜单表主要用于实现存储用户显示的菜单和拥有的权限,主要包括菜单名、访问权限和访问接口等字段;用户和角色中间表功能主要用于实现能将用户与角色关联起来,实现用户与角色多对多的关系;角色和菜单中间表主要用于定义某个角色可以访问哪些菜单。由于本系统采用Mybatis-plus 框架来关联Web 应用与数据库实现CRUD 操作,无需在数据库的表设计中添加外键,Mybatis-plus 默认使用生成ID,在项目的配置文件中配置即可。

图3 数据库物理模型

4 权限管理核心功能的实现

该权限管理系统将论述前端和后端的核心功能的实现过程。前端核心功能则是采用Vue.js 与Element-Plus 等技术简化UI 开发工作。Vue 基于标准HTML、CSS 和JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助开发者高效地开发用户界面[6]。Element-Plus 是一个基于Vue.js 的企业级UI 组件库,它包含了很多常用的UI 组件,如表格、表单、按钮、弹框等,可大大简化UI 开发工作。后端核心功能是采用Spring Security 与JWT 等技术实现对特定资源的访问,充分应用Spring Security 的认证和授权功能。后端核心功能类分别保存在配置包config 和控制器包controller中,如图4所示。

图4 后端核心功能类

4.1 身份认证的实现

4.1.1 身份认证前端的实现

身份认证之前需先通过表单收集登录用户的用户名和密码,如图5 所示,当用户输入完用户名和密码后,还需在“验证码”输入框输入其右边随机产生的字母图形码,防御通过机器人高频率地访问服务器,同时也可勾选表单左下角的“记住密码”单选框对当前密码进行保存,方便下次登录系统。若输入的信息都正确,点击“登录”按钮即可成功登录系统。

图5 系统登录页面

“登录”按钮的功能是该登录页面的核心功能,关键的javascript代码如下所示:

用户成功登录后会在浏览器的会话存储器中保存相应的数据,特别是token,如图6所示。

图6 会话存储器中保存的数据

4.1.2 身份认证后端的实现

后端采用Spring Security 对用户身份进行认证,其认证功能是验证试图要访问特定资源的人的身份,而授权则是用来确定允许谁可以访问特定的资源的作用。Spring Security 的深度防御措施则可以通过允许基于请求的授权和基于方法的授权来实现这一功能。

(1)用户身份认证环节的实现过程:当用户登录成功后,Web 服务器会根据设定的算法和JWT 的结构生成一个token,并将该token 返回给客户端,此时,token 将存储在缓存服务器中。接下来,客户端接收到信息,再根据Web 服务器来实现返回该用户所能访问的前端菜单的动态加载页面,从而实现为不同角色显示不同的页面效果的功能。当用户进行第二次登录时,只需要带上上一次服务器所返回的token 即可,无需再次进行账号和密码的验证。也就是说,系统此时只需要从用户提交的token当中去获取该用户的用户名,然后再从Redis服务器中通过这个用户名拿到一个token。如果此时的token相同,则开始检验该token是否过期,如果已经过期则会重新生成一个新的token。下面将通过2个类的部分功能来论证用户身份的认证过程。

控制层的“SysUserController.java”用户控制器类主要实现对用户名进行验证,代码及其关键注释如下:

(2)对特定资源访问授权的实现过程:当用户成功登录后,需要对其他的页面或资源进行访问,但由于token中包含了用户的基本信息和所能访问的资源,因此每次进行资源访问时,用户也只需要带上token即可。用户可以通过token获取来用户名,再通过用户名访问数据库,进而查询该用户是否有访问该API资源的权限,如果该用户拥有访问该资源的权限,就继续正常往下执行,否则将返回无权访问的提示。

当用户成功通过Spring Security 安全框架的认证和授权,程序的业务逻辑层会根据用户ID 获取用户权限信息,代码如下所示,程序运行时从控制台输出所获权限结果,如图7所示。

图7 控制台输出所获权限结果

4.2 对用户分配角色的实现

4.2.1 分配角色前端的实现

当登录用户的身份通过验证后即可进入到系统的首页。用户通过点击左侧菜单“用户管理”进入用户管理页面,该页面的功能非常丰富,如搜索用户信息、新增用户和对用户进行分配角色等,如图8所示。

图8 用户管理界面

由于用户需求的改变,要求将test02 用户增加“普遍角色”。为了实现该功能,需点击“分配角色”按钮,便弹出如图9 所示的对话框,当选择完所需角色后,点击“确定”按钮即可实现。该按钮核心的javascript代码和注释如下:

图9 对指定用户分配角色1

如图10 所示为成功地对test02 用户分配角色后的前面效果。

图10 指定用户分配角色2

4.2.2 分配角色后端的实现

对指定用户分配角色主要在系统用户控制类“SysUser-Controller.java”的grantRole()方法上实现,如下代码所示,需同时对该方法添加3 个注释:启用数据库事务处理的@Transactional;提交数据的影射@PostMapping,其路径参数中采用RESTful 架构来传递userId;@PreAuthorize 为用前授权判断,要求访问该方法前必须拥有访问角色的权限。

4.3 对角色权限分配的实现

4.3.1 对角色权限分配前端的实现

对于权限管理系统,给指定的角色进行权限分配显得非常重要功能之一。当在“角色管理”页面中点击“普通角色”的“分配权限”按钮后,便弹出如图11 所示的“分配权限”对话框,从中查看到“普通角色”的权限比较少,仅有对用户和角色进行查询,及访问业务的权限。根据系统功能需求,要对其添加权限:用户新增、重置密码和菜单查询,则勾选如图12 所示的对话框,最后点击“确认”按钮即可完成。“确认”按钮的javascript代码和注释如下:

图11 对角色分配权限前

图12 对角色分配权限后

4.3.2 对角色权限分配后端的实现

通过控制层的“SysRoleController.java”定义update-Menus()方法来处理前端提交的数据,该方法能实现更新角色权限信息。由于该方法需对数据库进行写操作,为保证数据的原子性,给该方法添加事务处理注解@Transactional,同时在所请求的url 中采用了RESTful 架构,方便对处理前端传来的数据。以下为对角色权限分配实现的Java代码:

4.4 对菜单配置权限的实现

4.4.1 对菜单配置权限前端的实现

为菜单配置相应的权限是本系统的核心功能之一,先前的功能必须获取相应的权限才能执行。下面将论述为“用户管理”新建权限分配的前端实现。当进入“权限管理”页面后,系统将查询出各级“菜单名称”的“权限标识”等信息,现需为“用户管理”新建一个用于“test 用户查询”的权限“system:user:query”,如图13所示,点击“确认”按钮后,成功地完成其权限的新建,如图14所示。“确认”按钮的javascript代码和注释如下:

图13 权限分配中

图14 权限分配后

4.4.2 对菜单配置权限后端的实现

后端为了响应前端对菜单添加或者修改权限的操作,需在控制层的“SysMenuController.java”类中定义save()方法来保存该操作的结果。该方法需添加2 个注解:用于url路由的@PostMapping;使用方法前需获取添加和编辑的权限@PreAuthorize。该方法接收的“SysRole”对象前需添加2 个注解:@RequestBoday 表示该对象应该绑定到web 请求的主体;@Valid 表示标记用于级联验证的属性、方法参数或方法返回类型。对菜单进行权限分配的核心Java 代码和注释如下:

5 结语

本系统基于Spring Security 安全框架搭建了一套安全可靠的权限管理系统,系统的实现采用了RBAC 模型、Mybatis-plus 框架和JWT 等技术,并结合Vue.js 和Element-Plus 等技术实现系统的前后端分离功能设计。本系统应用了微服务构架设计,减轻了后端服务器的运算速度,降低了数据存储产生的压力,同时,对外来的非法访问攻击产生防范作用,为信息系统实现了可靠的安全认证与授权管理等功能,更便于后续的移植与维护。

猜你喜欢

菜单按钮分配
当你面前有个按钮
中国新年菜单
应答器THR和TFFR分配及SIL等级探讨
遗产的分配
一种分配十分不均的财富
绩效考核分配的实践与思考
死循环
本月菜单
内心不能碰的按钮
一个“公海龟”的求偶菜单