[Java实战]Spring Boot 3 整合 Apache Shiro(二十一)

news2025/5/14 13:57:20

[Java实战]Spring Boot 3 整合 Apache Shiro(二十一)

引言

在复杂的业务系统中,安全控制(认证、授权、加密)是核心需求。相比于 Spring Security 的重量级设计,Apache Shiro 凭借其简洁的 API 和灵活的扩展性,成为许多开发者的优选方案。本文将手把手演示如何在 Spring Boot 3 中整合 Shiro 1.12.0+,实现完整的权限管理功能。

一、环境准备

  • openJDK 17+(Spring Boot 3 强制要求)
  • Spring Boot 3.4.5
  • Apache Shiro 1.12.0(支持 Jakarta EE 9+)
  • Maven/Gradle(本文使用 Maven)
  • Redis(可选,用于会话管理)

二、项目依赖配置

pom.xml 中添加关键依赖:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Shiro Core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.12.0</version>
            <classifier>jakarta</classifier>
        </dependency>
        <!-- Servlet API (兼容性) -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>

        </dependency>
</dependencies>

三、核心组件配置

1. Shiro 配置类

创建 ShiroConfig.java 定义安全规则:

@Configuration
public class ShiroConfig {

    // 注入自定义 Realm
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }

    // 配置 SecurityManager
    @Bean
    public SecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    // 配置 Shiro 过滤器
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();
        chain.addPathDefinition("/login", "anon");  // 匿名访问
        chain.addPathDefinition("/logout", "logout"); // 退出登录
        chain.addPathDefinition("/**", "authc"); // 需要认证
        return chain;
    }

    // 记住我功能
    @Bean
    public RememberMeManager rememberMeManager() {
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return rememberMeManager;
    }
}

2. 自定义 Realm 实现

创建 UserRealm.java 实现认证与授权逻辑:

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    // 授权逻辑
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        String username = (String) principals.getPrimaryPrincipal();
        
        // 查询用户角色和权限
        User user = userService.findByUsername(username);
        info.setRoles(user.getRoles());
        info.setStringPermissions(user.getPermissions());
        
        return info;
    }

    // 认证逻辑
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) 
        throws AuthenticationException {
        
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        User user = userService.findByUsername(username);

        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }
        
        return new SimpleAuthenticationInfo(
            username, 
            user.getPassword(), 
            ByteSource.Util.bytes(user.getSalt()),
            getName()
        );
    }
}

四、权限控制实战

1. 控制器层注解控制

在 Controller 方法上使用 Shiro 注解:

@RestController
@RequestMapping("/user")
public class UserController {

    @RequiresRoles("admin")  // 需要admin角色
    @GetMapping("/list")
    public ResponseEntity<List<User>> listUsers() {
        // 业务逻辑
    }

    @RequiresPermissions("user:delete") // 需要删除权限
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        // 业务逻辑
    }
}

2. 统一异常处理

通过 @ControllerAdvice 捕获 Shiro 异常:

@Slf4j
@ControllerAdvice
public class ShiroExceptionHandler {

    @ExceptionHandler(AuthorizationException.class)
    public ResponseEntity<ApiResponse<?>> handleAuthError(AuthorizationException e) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN)
                .body(new ApiResponse<>(403, "权限不足"));
    }

    @ExceptionHandler(AuthenticationException.class)
    public ResponseEntity<ApiResponse<?>> handleLoginError(AuthenticationException e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body(new ApiResponse<>(401, "认证失败"));
    }
}

五、高级功能扩展

1. 集成 Redis 会话管理

@Bean
public SessionDAO sessionDAO() {
    RedisSessionDAO sessionDAO = new RedisSessionDAO();
    sessionDAO.setRedisManager(redisManager());
    return sessionDAO;
}

@Bean
public RedisManager redisManager() {
    RedisManager manager = new RedisManager();
    manager.setHost("localhost:6379");
    manager.setDatabase(0);
    return manager;
}

2. 密码加密配置

@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    matcher.setHashAlgorithmName("SHA-256");
    matcher.setHashIterations(1024);
    matcher.setStoredCredentialsHexEncoded(false);
    return matcher;
}

// 在 Realm 中设置
userRealm.setCredentialsMatcher(hashedCredentialsMatcher());

六、常见问题排查

1. 权限注解不生效

  • 检查是否开启 AOP 支持:在配置类添加 @EnableAspectJAutoProxy
  • 确认方法为 public 且通过代理对象调用

2. 会话失效异常

  • 检查 Redis 连接配置
  • 确保 SessionDAO 实现已正确注入

七、性能优化建议

  1. 缓存授权信息:使用 CachingRealm 减少数据库查询
  2. 限制会话数量:配置 sessionManager 的全局会话上限
  3. 启用集群模式:通过 Redis 实现分布式会话

结语

通过本文,您已完成 Spring Boot 3 与 Apache Shiro 的深度整合。相比 Spring Security,Shiro 的配置更简洁,适合中小型项目快速实现安全控制。建议根据实际业务需求调整认证策略和缓存机制。

扩展阅读:Shiro官方文档

希望本教程对您有帮助,请点赞❤️收藏⭐关注支持!欢迎在评论区留言交流技术细节!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2375435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BlockMesh Ai项目 监控节点部署教程

项目介绍 BlockMesh 是一个创新、开放且安全的网络&#xff0c;允许用户轻松地将多余的带宽货币化。 它为用户提供了被动获利并参与人工智能数据层、在线隐私、开源和区块链行业前沿的绝佳机会。 此教程为Linux系统教程 教程开始 首先到这里注册账号&#xff0c;注册后保存…

【Bluedroid】蓝牙 HID DEVICE 初始化流程源码解析

本文深入剖析Android蓝牙协议栈中HID设备&#xff08;BT-HD&#xff09;服务的初始化与启用流程&#xff0c;从接口初始化、服务掩码管理、服务请求路由到属性回调通知&#xff0c;完整展现蓝牙HID服务激活的技术路径。通过代码逻辑梳理&#xff0c;揭示服务启用的核心机制&…

iOS创建Certificate证书、制作p12证书流程

一、创建Certificates 1、第一步得先在苹果电脑上创建一个.certSigningRequest的文件。首先打开钥匙串&#xff0c;使用快捷键【command空格】——输入【钥匙串】回车&#xff08;找不到就搜一下钥匙串访问使用手册&#xff09; 2、然后在苹果电脑的左上角菜单栏选择【钥匙串…

curl发送数据不为null,但是后端接收到为null

curl -X POST http://localhost:8080/xiaozhi/test --header "Content-Type: application/json" -d "{\"age\":123}"经过检查发现注解导入错误 正确的应该是 import org.springframework.web.bind.annotation.RequestBody;

blazor与硬件通信实现案例

在网页接入硬件交互通信方案这篇博客中,曾经提到了网页中接入各种硬件操作的方法,即通过Windows Service作为指令的中转,并建立websocket通信连接,进而实现接入硬件的各种操作。这篇博客就以实际的案例来讲解具体怎么实现。 一、建立Windows Service项目 比如我就建立了一…

Linux下mysql的安装与远程链接

linux安装mysql 01下载依赖&#xff1a; 找到网址/download下&#xff1a; 最下面MySQL Community&#xff08;mysql社区版&#xff09; 选择MySQL Community Server 选择对应的mysql版本 操作系统版本选择 根据操作系统的版本选择具体版本号 下载离线版本 安装包详情 0…

【HT周赛】T3.二维平面 题解(分块:矩形chkmax,求矩形和)

题意 需要维护 n n n \times n nn 平面上的整点&#xff0c;每个点 ( x , y ) (x, y) (x,y) 有权值 V ( x , y ) V(x, y) V(x,y)&#xff0c;初始都为 0 0 0。 同时给定 n n n 次修改操作&#xff0c;每次修改给出 x 1 , x 2 , y 1 , y 2 , v x_1, x_2, y_1, y_2, v x…

qemu热迁移后内存占用突增问题

1.问题描述 虚拟机配置了memoryBackingmemfd的情况下&#xff0c;热迁移虚拟机后&#xff0c;在目的节点 qemu-kvm 进程占用 rss 会突增很多。 如果去掉这个配置没这个现象。 <memoryBacking><source typememfd/> </memoryBacking>2.问题现象 2.1 不配置…

鸿蒙 Core File Kit(文件基础服务)之简单使用文件

查看常用的沙箱目录 应用沙箱文件访问关系图 应用文件目录结构图 查看常用的沙箱目录 Entry Component struct Index {build() {Button(查看常用的沙箱目录).onClick(_>{let ctx getContext() // UI下只能使用这个方法&#xff0c;不能 this.contextconsole.log(--应用缓存…

基于Qt的app开发第七天

写在前面 笔者是大一下计科生&#xff0c;标题这个项目是笔者这个学期的课设&#xff0c;与学长共创&#xff0c;我负责客户端部分&#xff0c;现在已经实现了待办板块的新建、修改。 这个项目目前已经走上正轨了&#xff0c;博主也实现了主要功能的从无到有&#xff…

目标检测任务常用脚本1——将YOLO格式的数据集转换成VOC格式的数据集

在目标检测任务中&#xff0c;不同框架使用的标注格式各不相同。常见的框架中&#xff0c;YOLO 使用 .txt 文件进行标注&#xff0c;而 PASCAL VOC 则使用 .xml 文件。如果你需要将一个 YOLO 格式的数据集转换为 VOC 格式以便适配其他模型&#xff0c;本文提供了一个结构清晰、…

NLTK库: 数据集3-分类与标注语料(Categorized and Tagged Corpora)

NLTK库: 数据集3-分类与标注语料&#xff08;Categorized and Tagged Corpora&#xff09; 1.二分类语料 主要是电影语料&#xff0c;和情绪(积极消极、主观客观)有关&#xff0c;有以下2个语料&#xff1a; 1.1 movie_reviews: IMDb 影评 IMDb&#xff08;Internet Movie …

uni-app学习笔记五-vue3响应式基础

一.使用ref定义响应式变量 在组合式 API 中&#xff0c;推荐使用 ref() 函数来声明响应式状态&#xff0c;ref() 接收参数&#xff0c;并将其包裹在一个带有 .value 属性的 ref 对象中返回 示例代码&#xff1a; <template> <view>{{ num1 }}</view><vi…

ElasticSeach快速上手笔记-入门篇

由来 Elasticsearch 是一个基于 Apache Lucene 构建的分布式、高扩展、近实时的搜索与数据分析引擎&#xff0c;能够高效处理结构化和非结构化数据的全文检索及复杂分析 搜索&#xff0c;即用户在平台如百度进行输入关键词&#xff0c;由后端给出搜索结果数据进行返回&#x…

《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》

1 read-thread 1.1 初始化部分 1.分配. avformat_alloc_context 创建上下⽂ ic avformat_alloc_context();if (!ic) {av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");ret AVERROR(ENOMEM);goto fail;}2 ic->interrupt_callback.callback deco…

MySQL推荐书单:从入门到精通

给大家介绍一些 MySQL 从入门到精通的经典书单&#xff0c;可以基于不同学习阶段的需求进行选择。 入门 MySQL必知必会 这本书继承了《SQL必知必会》的优点&#xff0c;专门针对 MySQL 用户&#xff0c;没有过多阐述数据库基础理论&#xff0c;而是紧贴实战&#xff0c;直接从…

【Nacos】env NACOS_AUTH_TOKEN must be set with Base64 String.

【Nacos】env NACOS_AUTH_TOKEN must be set with Base64 String. 问题描述 env NACOS_AUTH_TOKEN must be set with Base64 String.原因分析 从错误日志中可以看出&#xff0c;Nacos 启动失败的原因是缺少必要的环境变量 NACOS_AUTH_TOKEN。 NACOS_AUTH_TOKEN: Nacos 用于生…

秋招准备——2.跨时钟相关

格雷码异步FIFO跨时钟域处理 格雷码 一、格雷码规律 相邻性&#xff1a;相邻两个数的格雷码只有一位不同&#xff0c;例如&#xff1a; 0000 → 0001&#xff08;仅最低位变化&#xff09;0001 → 0011&#xff08;仅次低位变化&#xff09;0011 → 0010&#xff08;仅最低位…

激光打印机常见打印故障简单处理意见

一、 问题描述&#xff1a; 给打印机更换新的硒鼓时拉开硒鼓封条时有微量碳粉带出&#xff1b; 原因&#xff1a; 出厂打印测试时&#xff0c;可能会有微量碳粉在磁辊上或者磁辊仓&#xff1b; 解决方法&#xff1a; 擦干净即可正常使用&#xff1b; 二、 问题描述&…

【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)

文章目录 为什么选择VSCode作为C/C开发工具&#xff1f;一、VSCode安装过程&#xff08;超简单&#xff01;&#xff09;二、VSCode中文界面设置&#xff08;再也不用对着英文发愁&#xff01;&#xff09;三、安装C/C插件&#xff08;编程必备神器&#xff01;&#xff09;四、…