当前位置: 首页 > news >正文

使用 Shiro 和 JPA 结合 MySQL 实现一个简易权限管理系统

1. 项目设置

首先,确保你的项目已经配置好 Maven 或 Gradle 依赖管理工具,并添加以下依赖:

Maven 依赖

<dependencies><!-- Shiro 核心库 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.9.0</version></dependency><!-- Shiro Web 支持 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>1.9.0</version></dependency><!-- JPA 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><!-- Spring Boot Web 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot 安全支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- 其他依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
</dependencies>

2. 配置 MySQL 数据库

在 application.properties 或 application.yml 中配置 MySQL 数据库连接:

spring.datasource.url=jdbc:mysql://localhost:3306/shiro_demo
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

3. 创建实体类

使用 JPA 创建用户、角色和权限的实体类。

用户实体 (User)
@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;@ManyToMany(fetch = FetchType.EAGER)private Set<Role> roles;// Getters and Setters
}
角色实体 (Role)

@Entity
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany(fetch = FetchType.EAGER)private Set<Permission> permissions;// Getters and Setters
}
权限实体 (Permission)
@Entity
public class Permission {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;// Getters and Setters
}

4. 创建 Repository 接口

使用 Spring Data JPA 创建 Repository 接口。

public interface UserRepository extends JpaRepository<User, Long> {User findByUsername(String username);
}public interface RoleRepository extends JpaRepository<Role, Long> {
}public interface PermissionRepository extends JpaRepository<Permission, Long> {
}

5. 配置 Shiro

创建一个 Shiro 配置类,配置 Realm 和 SecurityManager。

@Configuration
public class ShiroConfig {@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();filterChainDefinitionMap.put("/login", "anon");filterChainDefinitionMap.put("/logout", "logout");filterChainDefinitionMap.put("/**", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}@Beanpublic SecurityManager securityManager(Realm realm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(realm);return securityManager;}@Beanpublic Realm realm(UserRepository userRepository) {return new JpaRealm(userRepository);}
}

6. 自定义 Realm

创建一个自定义的 Realm 类,用于从数据库中获取用户信息。

public class JpaRealm extends AuthorizingRealm {private final UserRepository userRepository;public JpaRealm(UserRepository userRepository) {this.userRepository = userRepository;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String username = (String) principals.getPrimaryPrincipal();User user = userRepository.findByUsername(username);SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();for (Role role : user.getRoles()) {authorizationInfo.addRole(role.getName());for (Permission permission : role.getPermissions()) {authorizationInfo.addStringPermission(permission.getName());}}return authorizationInfo;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();User user = userRepository.findByUsername(username);if (user == null) {throw new UnknownAccountException("User not found");}return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());}
}

7. 创建控制器

创建一个简单的控制器来处理登录和访问控制。

@Controller
public class HomeController {@GetMapping("/home")public String home() {return "home";}@GetMapping("/login")public String login() {return "login";}@PostMapping("/login")public String doLogin(@RequestParam String username, @RequestParam String password) {Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password);try {subject.login(token);return "redirect:/home";} catch (AuthenticationException e) {return "redirect:/login?error";}}@GetMapping("/logout")public String logout() {Subject subject = SecurityUtils.getSubject();subject.logout();return "redirect:/login";}
}

8. 创建视图

创建简单的 Thymeleaf 视图来展示登录页面和主页。

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>Login</title>
</head>
<body><h1>Login</h1><form th:action="@{/login}" method="post"><label for="username">Username:</label><input type="text" id="username" name="username" required><br><label for="password">Password:</label><input type="password" id="password" name="password" required><br><button type="submit">Login</button></form><p th:if="${param.error}" style="color: red;">Invalid username or password</p>
</body>
</html>

运行 HTML

home.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>Home</title>
</head>
<body><h1>Welcome to the Home Page</h1><a th:href="@{/logout}">Logout</a>
</body>
</html>

9. 运行项目

启动 Spring Boot 应用程序,访问 http://localhost:8080/login 进行登录。登录成功后,你将能够访问 /home 页面。

10. 权限控制

你可以在控制器中使用 @RequiresRoles 或 @RequiresPermissions 注解来控制访问权限。

@Controller
public class AdminController {@RequiresRoles("admin")@GetMapping("/admin")public String admin() {return "admin";}
}

11、创建测试数据脚本

-- 插入权限数据
INSERT INTO permission (name) VALUES ('user:read');
INSERT INTO permission (name) VALUES ('user:write');
INSERT INTO permission (name) VALUES ('admin:read');
INSERT INTO permission (name) VALUES ('admin:write');-- 插入角色数据
INSERT INTO role (name) VALUES ('user');
INSERT INTO role (name) VALUES ('admin');-- 关联角色和权限
-- 用户角色拥有 user:read 和 user:write 权限
INSERT INTO role_permissions (role_id, permissions_id) VALUES ((SELECT id FROM role WHERE name = 'user'),(SELECT id FROM permission WHERE name = 'user:read')
);
INSERT INTO role_permissions (role_id, permissions_id) VALUES ((SELECT id FROM role WHERE name = 'user'),(SELECT id FROM permission WHERE name = 'user:write')
);-- 管理员角色拥有所有权限
INSERT INTO role_permissions (role_id, permissions_id) VALUES ((SELECT id FROM role WHERE name = 'admin'),(SELECT id FROM permission WHERE name = 'user:read')
);
INSERT INTO role_permissions (role_id, permissions_id) VALUES ((SELECT id FROM role WHERE name = 'admin'),(SELECT id FROM permission WHERE name = 'user:write')
);
INSERT INTO role_permissions (role_id, permissions_id) VALUES ((SELECT id FROM role WHERE name = 'admin'),(SELECT id FROM permission WHERE name = 'admin:read')
);
INSERT INTO role_permissions (role_id, permissions_id) VALUES ((SELECT id FROM role WHERE name = 'admin'),(SELECT id FROM permission WHERE name = 'admin:write')
);-- 插入用户数据
-- 密码使用 Shiro 的加密方式(例如 MD5 加密)
INSERT INTO user (username, password) VALUES ('user1', 'password1');
INSERT INTO user (username, password) VALUES ('admin1', 'password1');-- 关联用户和角色
-- 用户 user1 拥有 user 角色
INSERT INTO user_roles (user_id, roles_id) VALUES ((SELECT id FROM user WHERE username = 'user1'),(SELECT id FROM role WHERE name = 'user')
);-- 用户 admin1 拥有 admin 角色
INSERT INTO user_roles (user_id, roles_id) VALUES ((SELECT id FROM user WHERE username = 'admin1'),(SELECT id FROM role WHERE name = 'admin')
);

 测试登录

启动应用程序后,使用以下测试用户登录:

  • 用户user1,密码: password1,角色: user

  • 用户admin1,密码: password1,角色: admin

登录后,你可以根据角色和权限访问不同的页面。

相关文章:

使用 Shiro 和 JPA 结合 MySQL 实现一个简易权限管理系统

1. 项目设置 首先&#xff0c;确保你的项目已经配置好 Maven 或 Gradle 依赖管理工具&#xff0c;并添加以下依赖&#xff1a; Maven 依赖 <dependencies><!-- Shiro 核心库 --><dependency><groupId>org.apache.shiro</groupId><artifactI…...

DeepSeek与医院电子病历的深度融合路径:本地化和上云差异化分析

一、引言 1.1 研究背景与意义 在医疗信息化快速发展的当下,电子病历系统已成为医院信息管理的核心构成。电子病历(EMR)系统,是指医务人员在医疗活动过程中,使用医疗机构信息系统生成的文字、符号、图标、图形、数据、影像等数字化信息,并能实现存储、管理、传输和重现的…...

设计模式:代理模式

代理模式是很常见的设计模式&#xff0c;即使没有专门学习过这种设计模式&#xff0c;在工作中也一定用过这种设计模式。在实际生活中&#xff0c;代理模式也是常见的&#xff0c;比如内阁首辅相对于皇帝&#xff0c;前者是后者的代理&#xff0c;内阁首辅收到奏折时&#xff0…...

141,【1】buuctf web [SUCTF 2019]EasyWeb

进入靶场 代码审计 <?php // 定义函数get_the_flag&#xff0c;功能是处理文件上传相关操作 function get_the_flag() {// 注释说明&#xff1a;webadmin会每隔20分钟删除用户上传的文件$userdir "upload/tmp_" . md5($_SERVER[REMOTE_ADDR]);// 检查用户目录…...

破解微服务疑难杂症:2025年全解决方案

微服务架构已经成为现代软件开发的主流选择&#xff0c;其优势在于能够将复杂的系统拆分为独立的服务模块&#xff0c;方便开发和维护。然而&#xff0c;在微服务的实施过程中&#xff0c;开发者往往会面临许多挑战&#xff0c;如服务间通信、数据一致性、性能优化和故障处理等…...

Node.js 中的 Event 模块详解

Node.js 中的 Event 模块是实现事件驱动编程的核心模块。它基于观察者模式&#xff0c;允许对象&#xff08;称为“事件发射器”&#xff09;发布事件&#xff0c;而其他对象&#xff08;称为“事件监听器”&#xff09;可以订阅并响应这些事件。这种模式非常适合处理异步操作和…...

EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS

随着互联网技术的飞速发展&#xff0c;实时通信&#xff08;RTC&#xff09;已经成为现代应用中不可或缺的一部分。无论是视频会议、在线教育、远程医疗&#xff0c;还是社交娱乐&#xff0c;实时通信技术都在其中扮演着重要角色。 然而&#xff0c;WebRTC技术在PC和移动端的支…...

pycharm社区版有个window和arm64版本,到底下载哪一个?还有pycharm官网

首先pycharm官网是这一个。我是在2025年2月16日9:57进入的网站。如果网站还没有更新的话&#xff0c;那么就往下滑一下找到 community Edition,这个就是社区版了免费的。PyCharm&#xff1a;适用于数据科学和 Web 开发的 Python IDE 适用于数据科学和 Web 开发的 Python IDE&am…...

【玩转全栈】----Django模板语法、请求与响应

目录 一、引言 二、模板语法 三、传参 1、视图函数到模板文件 2、模板文件到视图函数 四、引入静态文件 五、请求与响应 ?1、请求 2、响应 六、综合小案例 1、源码展示 2、注意事项以及部分解释 3、展示 一、引言 像之前那个页面&#xff0c;太过简陋&#xff0c;而且一个完整…...

网络安全:挑战、技术与未来发展

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 在数字化时代&#xff0c;网络安全&#xff08;Cybersecurity&#xff09;已成为全球关注的焦点。随着云计算、大数据、…...

DeepSeek 服务器繁忙的全面解决方案

目录 引文 正文 一、 服务器繁忙的原因分析 二、 解决方案 2.1切换网络 2.2使用网络加速工具 2.3错峰使用DeepSeek 2.4本地部署 2.5调用API 三、官方动态 一、技术研发与产品升级 二、市场合作与商业化进展 三、区域化布局与产业赋能 四、未来规划与社会责任 结语…...

将OpenWrt部署在x86服务器上

正文共&#xff1a;1234 字 40 图&#xff0c;预估阅读时间&#xff1a;2 分钟 如果你问ChatGPT有哪些开源的SD-WAN方案&#xff0c;他会这样答复你&#xff1a; 我们看到&#xff0c;OpenWrt也属于比较知名的开源SD-WAN解决方案。当然&#xff0c;在很久之前&#xff0c;我就发…...

计算机视觉:卷积神经网络(CNN)基本概念(一)

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络 一、引言 卷积神经网络&…...

企业文件共享中的权限管理与安全风险防范

在企业的日常运营中&#xff0c;文件共享是必不可少的一项工作。然而&#xff0c;文件共享过程中如果权限管理不当&#xff0c;极易引发安全风险&#xff0c;导致企业敏感信息泄露。因此&#xff0c;加强文件共享中的权限管理与安全风险防范&#xff0c;对于保障企业信息安全至…...

使用DeepSeek建立一个智能聊天机器人0.12

为了确保这段代码能够在Windows和Linux系统上都能正常运行,我考虑以下几个方面: 路径分隔符:在Windows和Linux中,文件路径的分隔符不同。Windows使用反斜杠(\),而Linux使用正斜杠(/)。我们可以使用 os.path.join 来处理路径,以确保跨平台兼容性。 消息框:tkinter.…...

国家队出手!DeepSeek上线国家超算互联网平台!

目前,国家超算互联网平台已推出 DeepSeek – R1 模型的 1.5B、7B、8B、14B 版本,后续还会在近期更新 32B、70B 等版本。 DeepSeek太火爆了!在这个春节档,直接成了全民热议的话题。 DeepSeek也毫无悬念地干到了全球增速最快的AI应用。这几天,国内的云计算厂家都在支持Dee…...

Deep seek学习日记1

Deepseek最强大的就是它的深度思考&#xff0c;并且展现了它的思考过程。 五种可使用Deep seek的方式&#xff08;应该不限于这五种&#xff0c;后续嵌入deepseek的应该更多&#xff0c;多了解一点因为官网容易崩~~&#xff09;&#xff1a; 1.deep seek官网 2.硅基流动silicon…...

乐理笔记(持续更新)

单音与音程 单音&#xff1a;由一个音组成。 音程&#xff1a;由两个音组成&#xff0c;表示两个音之间的音高距离。 如何数音程&#xff1a; 单音程&#xff1a;9 - X&#xff0c;性质相反。例如&#xff0c;9度音程减去某个数&#xff0c;性质会相反。 复音程&#xff1a…...

【动态路由】系统Web URL资源整合系列(后端技术实现)【nodejs实现】

需求说明 软件功能需求&#xff1a;反向代理功能&#xff08;描述&#xff1a;apollo、eureka控、apisix、sentinel、普米、kibana、timetask、grafana、hbase、skywalking-ui、pinpoint、cmak界面、kafka-map、nacos、gateway、elasticsearch、 oa-portal 业务应用等多个web资…...

PHP高效、轻量级表格数据处理库 OpenSpout ,很好用

OpenSpout 是一个高效、轻量级的 PHP 库&#xff0c;用于处理电子表格文件&#xff08;如 Excel 和 CSV&#xff09;。它支持读取和写入大型文件&#xff0c;且内存占用低。本文将详细介绍如何安装和使用 OpenSpout。 目录 安装 基本使用 高级功能 参考文档 安装 OpenSp…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...