Spring Boot整合Apache Shiro实现安全认证与权限控制
1. Apache Shiro与Spring Boot整合概述在Java应用开发中安全机制是不可或缺的核心组件。Apache Shiro作为轻量级安全框架相比Spring Security具有更简单的API和更低的认知成本。我曾在多个生产项目中采用Shiro进行权限控制其简洁的设计哲学让开发团队能够快速上手。Shiro的核心优势在于它将安全操作抽象为四个基础概念认证Authentication、授权Authorization、会话管理Session Management和加密Cryptography。这种清晰的边界划分使得开发者可以按需使用各个模块。例如在最近的一个电商项目中我们仅用两天就完成了从零到生产的权限系统搭建。2. 环境准备与基础配置2.1 依赖管理在Spring Boot项目中引入Shiro需要添加以下核心依赖dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring-boot-starter/artifactId version1.9.0/version /dependency建议使用starter包而非单独的shiro-core和shiro-spring因为它会自动处理许多配置项。我曾遇到过手动配置时Bean初始化顺序问题starter包完美解决了这个痛点。2.2 基础配置类创建ShiroConfig配置类时需要注意几个关键点Configuration public class ShiroConfig { Bean public SessionManager sessionManager() { DefaultWebSessionManager manager new DefaultWebSessionManager(); manager.setSessionIdUrlRewritingEnabled(false); // 关闭URL重写 return manager; } Bean public DefaultWebSecurityManager securityManager(Realm realm) { DefaultWebSecurityManager manager new DefaultWebSecurityManager(); manager.setRealm(realm); manager.setRememberMeManager(null); // 禁用rememberMe return manager; } }特别提示在生产环境中务必关闭sessionIdUrlRewriting否则可能导致会话固定攻击。我在一次安全审计中就发现过因此导致的中危漏洞。3. 认证与授权实现3.1 自定义Realm开发Realm是Shiro与业务系统对接的桥梁需要重点实现两个方法public class CustomRealm extends AuthorizingRealm { Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) { String username (String) token.getPrincipal(); User user userService.findByUsername(username); if(user null) { throw new UnknownAccountException(用户不存在); } return new SimpleAuthenticationInfo( user, // 身份主体 user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName() ); } Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { User user (User) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info new SimpleAuthorizationInfo(); // 添加角色和权限 info.setRoles(roleService.getRoleCodes(user.getId())); info.setStringPermissions(permissionService.getPermissions(user.getId())); return info; } }3.2 密码加密策略Shiro推荐使用HashedCredentialsMatcher进行密码比对Bean public HashedCredentialsMatcher credentialsMatcher() { HashedCredentialsMatcher matcher new HashedCredentialsMatcher(); matcher.setHashAlgorithmName(SHA-256); matcher.setHashIterations(1000); matcher.setStoredCredentialsHexEncoded(false); return matcher; }在用户注册时需要采用相同的算法加密public String encryptPassword(String password, String salt) { return new SimpleHash( SHA-256, password, ByteSource.Util.bytes(salt), 1000 ).toBase64(); }4. 权限控制实战4.1 URL拦截配置ShiroFilterFactoryBean是配置请求拦截的核心Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean factory new ShiroFilterFactoryBean(); factory.setSecurityManager(securityManager); MapString, String filterMap new LinkedHashMap(); // 静态资源放行 filterMap.put(/static/**, anon); // 登录接口放行 filterMap.put(/api/login, anon); // 管理员路径需要admin角色 filterMap.put(/admin/**, roles[admin]); // 其他请求需要认证 filterMap.put(/**, authc); factory.setFilterChainDefinitionMap(filterMap); return factory; }4.2 注解式权限控制除了URL配置还可以使用注解RequiresPermissions(user:create) PostMapping(/users) public Result createUser(RequestBody User user) { // 创建用户逻辑 }支持的注解包括RequiresAuthenticationRequiresUserRequiresGuestRequiresRolesRequiresPermissions5. 会话管理与缓存5.1 分布式会话方案在集群环境中需要配置分布式会话Bean public SessionDAO sessionDAO() { RedisSessionDAO dao new RedisSessionDAO(); dao.setRedisManager(redisManager()); dao.setSessionIdGenerator(new JavaUuidSessionIdGenerator()); dao.setExpire(1800); // 30分钟过期 return dao; }5.2 缓存配置权限信息通常需要缓存Bean public CacheManager cacheManager() { RedisCacheManager cacheManager new RedisCacheManager(); cacheManager.setRedisManager(redisManager()); cacheManager.setKeyPrefix(shiro:cache:); return cacheManager; }6. 常见问题排查6.1 认证失败处理在登录控制器中需要处理各种异常PostMapping(/login) public Result login(RequestBody LoginDTO dto) { try { Subject subject SecurityUtils.getSubject(); UsernamePasswordToken token new UsernamePasswordToken( dto.getUsername(), dto.getPassword() ); subject.login(token); return Result.success(); } catch (UnknownAccountException e) { return Result.fail(账号不存在); } catch (IncorrectCredentialsException e) { return Result.fail(密码错误); } catch (LockedAccountException e) { return Result.fail(账号已锁定); } }6.2 权限缓存问题当用户权限变更时需要清除缓存public void clearAuthorizationCache(String username) { SimplePrincipalCollection principals new SimplePrincipalCollection( username, realm.getName() ); AuthorizationCache cache ((AuthorizingRealm)realm).getAuthorizationCache(); if(cache ! null) { cache.remove(principals); } }7. 进阶功能实现7.1 JWT集成对于前后端分离项目可以整合JWTpublic class JwtFilter extends AuthenticatingFilter { Override protected AuthenticationToken createToken( ServletRequest request, ServletResponse response ) { String token getRequestToken(request); return new JwtToken(token); } Override protected boolean onAccessDenied( ServletRequest request, ServletResponse response ) throws Exception { executeLogin(request, response); return true; } }7.2 动态权限控制实现数据库驱动的动态权限Bean public FilterChainDefinitionMap filterChainDefinitionMap() { DynamicFilterChainDefinition chain new DynamicFilterChainDefinition(); chain.addPathDefinition(/**, anon); // 从数据库加载权限配置 ListPermission permissions permissionService.listAll(); permissions.forEach(p - { chain.addPathDefinition( p.getUrl(), perms[ p.getCode() ] ); }); return chain; }8. 性能优化建议8.1 缓存策略优化权限信息建议设置较长的缓存时间如12小时会话信息根据业务需求设置通常30分钟-2小时使用二级缓存内存缓存 Redis缓存8.2 减少授权检查对于频繁访问的接口可以采用白名单机制权限预检查批量权限验证我在处理一个高并发系统时通过预加载用户权限到本地缓存使权限验证速度提升了8倍。

相关新闻

计算机毕业设计之net法院庭审辅助系统的研究与发现

计算机毕业设计之net法院庭审辅助系统的研究与发现

随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代&#xf…

2026/10/3 5:51:26 阅读更多 →
SpringBoot+Vue高校固定资产管理系统毕设全流程实战指南

SpringBoot+Vue高校固定资产管理系统毕设全流程实战指南

1. 先搞清楚这个毕设项目到底要做什么 如果你正在为计算机专业的毕业设计发愁,尤其是题目里带着“SpringbootVUE高校固定资产管理系统”这种关键词,那这篇文章就是为你准备的。这不是一个简单的技术堆砌教程,而是帮你理清从选题、开题到最终答…

2026/10/12 2:03:24 阅读更多 →
HarmonyOS7 基础单选项:用 Radio 做好单项选择

HarmonyOS7 基础单选项:用 Radio 做好单项选择

文章目录前言先看这个案例解决什么状态为什么这样设计关键代码拆开看完整代码落地时我会怎么改前言 这组案例开始进入选择类和调节类组件,写业务页面时会经常遇到。这个案例围绕 Radio 基础互斥选择 展开,重点不是把属性背下来,而是弄清楚状…

2026/10/16 2:55:25 阅读更多 →

最新新闻

深度学习环境配置终极指南:PyTorch+CUDA+cuDNN版本匹配实战

深度学习环境配置终极指南:PyTorch+CUDA+cuDNN版本匹配实战

搞了这么多年深度学习,我发现自己花在“配置环境”上的时间,一点不比调模型的时间少。PyTorch CUDA cuDNN这套组合,几乎是每个深度学习开发者的必经之路,也是最容易让人劝退的一步。网上教程一搜一大把,但版本匹配问…

2026/10/16 17:29:44 阅读更多 →
OpenCV霍夫变换圆检测原理与工程调优实战

OpenCV霍夫变换圆检测原理与工程调优实战

1. 项目概述:为什么圆检测不是“画个圈”那么简单OpenCV里的霍夫变换圆检测,听起来像是调个函数、设几个参数就能出结果的“一键操作”。但我在带某高校图像处理实验课时发现,超过七成的学生第一次跑通代码后,要么根本检不出图中的…

2026/10/16 17:29:43 阅读更多 →
从VGG16看卷积网络深度设计:小卷积核堆叠与迁移学习价值

从VGG16看卷积网络深度设计:小卷积核堆叠与迁移学习价值

前两天有个朋友发来一段代码,说他在某个小数据集上用VGG16做迁移学习,效果比一些看起来“更新”的网络还好,就是跑得慢。我顺手把2014年那篇《Very Deep Convolutional Networks for Large-Scale Image Recognition》翻出来又读了一遍。这篇论…

2026/10/16 17:29:43 阅读更多 →
会务小程序行政自己能搭吗?卡点就三步,附一张能当场验的清单

会务小程序行政自己能搭吗?卡点就三步,附一张能当场验的清单

单位办会,最常听到的一句话是"要做会务小程序啊?这个得找技术部门"。这句话现在不太站得住了。会务小程序这件事,早就过了要技术介入的阶段。真正卡住行政的不是能力,是三个很具体的坎:不会设计、不会配置、…

2026/10/16 17:28:42 阅读更多 →
StandardScaler保存的正确姿势:跨版本兼容与安全序列化

StandardScaler保存的正确姿势:跨版本兼容与安全序列化

1. 为什么StandardScaler的“保存”不是调用save()那么简单刚接触机器学习模型持久化的开发者,常会下意识地在StandardScaler对象上调用.save()或.dump()——结果要么报错AttributeError,要么保存下来的东西根本没法用。这不是你记错了API,而…

2026/10/16 17:28:42 阅读更多 →
GPT生成式预训练全解析:从架构原理到微调实践

GPT生成式预训练全解析:从架构原理到微调实践

1. 生成式预训练到底解决了什么问题先把话说在前面:GPT这几年几乎成了大模型的代名词,但很多人其实没搞明白,它最初提出的"生成式预训练"到底解决了什么问题。如果你把时间拨回2018年,那时候做NLP的主流思路是&#xff…

2026/10/16 17:28:42 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →