Apache Shiro框架:Java安全认证与授权实践指南
1. Shiro框架概述Apache Shiro是一个强大且易用的Java安全框架它为应用程序提供了认证、授权、加密和会话管理等功能。作为一个轻量级的安全框架Shiro的设计理念是简化应用程序安全性的实现同时保持足够的灵活性和扩展性。Shiro的核心功能可以概括为以下四个方面认证(Authentication)验证用户身份通常就是我们常说的登录过程授权(Authorization)访问控制决定用户能做什么会话管理(Session Management)用户特定的时间敏感状态管理密码加密(Cryptography)保护数据安全防止敏感信息泄露与其他安全框架相比Shiro的主要优势在于其简单性和易用性。它不需要依赖任何容器或框架可以轻松集成到任何Java应用程序中无论是简单的命令行程序还是复杂的企业级Web应用。2. Shiro核心组件解析2.1 Subject安全操作的主体Subject是Shiro的核心概念代表当前与应用程序交互的用户。这个用户可以是人也可以是第三方服务、后台进程等。Subject封装了当前用户的所有安全操作包括// 获取当前Subject Subject currentUser SecurityUtils.getSubject(); // 登录 currentUser.login(token); // 检查角色 currentUser.hasRole(admin); // 检查权限 currentUser.isPermitted(user:delete);Subject实际上是一个门面(Facade)模式它将大部分安全操作委托给SecurityManager处理。2.2 SecurityManager安全管理的核心SecurityManager是Shiro架构的心脏负责协调所有安全组件的工作。它管理着所有Subject的安全操作并提供以下服务认证管理授权管理会话管理缓存管理在应用程序中通常只需要配置一个SecurityManager实例。配置示例如下[main] # 配置Realm myRealm com.example.MyRealm securityManager.realms $myRealm # 配置缓存管理器 cacheManager org.apache.shiro.cache.ehcache.EhCacheManager securityManager.cacheManager $cacheManager2.3 Realm安全数据桥梁Realm充当Shiro与应用程序安全数据源之间的桥梁。当需要认证用户或检查权限时Shiro会从配置的Realm中查询相关数据。Shiro支持多种Realm实现IniRealm从INI配置文件中读取用户和角色信息JdbcRealm通过JDBC从数据库中获取安全数据LdapRealm连接LDAP目录服务ActiveDirectoryRealm集成Active Directory开发者也可以自定义Realm实现public class MyCustomRealm extends AuthorizingRealm { // 认证逻辑 Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) { // 实现认证逻辑 } // 授权逻辑 Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 实现授权逻辑 } }3. 认证流程深度解析3.1 认证基本流程Shiro的认证流程可以概括为以下步骤用户提交身份凭证通常是用户名/密码创建AuthenticationToken对象封装凭证调用Subject.login()方法SecurityManager处理认证请求Realm验证凭证并返回认证信息认证成功或失败处理代码示例// 1. 获取当前用户 Subject currentUser SecurityUtils.getSubject(); // 2. 创建认证令牌 UsernamePasswordToken token new UsernamePasswordToken(username, password); try { // 3. 登录认证 currentUser.login(token); // 认证成功处理 } catch (AuthenticationException ae) { // 认证失败处理 }3.2 认证流程源码分析让我们深入Shiro源码看看认证过程是如何实现的Subject.login()调用// DelegatingSubject.java public void login(AuthenticationToken token) throws AuthenticationException { clearRunAsIdentitiesInternal(); Subject subject securityManager.login(this, token); // 处理认证结果... }SecurityManager处理// DefaultSecurityManager.java public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException { AuthenticationInfo info authenticate(token); Subject loggedIn createSubject(token, info, subject); onSuccessfulLogin(token, info, loggedIn); return loggedIn; }Authenticator认证// ModularRealmAuthenticator.java protected AuthenticationInfo doAuthenticate(AuthenticationToken token) { CollectionRealm realms getRealms(); if (realms.size() 1) { return doSingleRealmAuthentication(realms.iterator().next(), token); } else { return doMultiRealmAuthentication(realms, token); } }Realm验证// AuthenticatingRealm.java public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) { // 1. 尝试从缓存获取 AuthenticationInfo info getCachedAuthenticationInfo(token); if (info null) { // 2. 缓存中没有则调用doGetAuthenticationInfo info doGetAuthenticationInfo(token); // 3. 缓存认证信息 cacheAuthenticationInfoIfPossible(token, info); } // 4. 验证凭证 if (info ! null) { assertCredentialsMatch(token, info); } return info; }3.3 密码匹配与加密Shiro提供了强大的密码匹配和加密功能密码匹配器// 配置密码匹配器 HashedCredentialsMatcher matcher new HashedCredentialsMatcher(); matcher.setHashAlgorithmName(SHA-256); matcher.setHashIterations(1024); myRealm.setCredentialsMatcher(matcher);密码加密// 生成加密密码 String hashedPassword new Sha256Hash(password, salt, 1024).toBase64();盐值使用// 在Realm中设置盐值 info.setCredentialsSalt(ByteSource.Util.bytes(salt));4. 授权机制详解4.1 授权基本概念Shiro的授权模型基于三个核心概念权限(Permission)定义具体的操作权限如user:create角色(Role)权限的集合如admin角色可能包含所有用户管理权限访问控制检查用户是否具有执行某个操作的权限Shiro支持多种授权方式编程式授权if (subject.hasRole(admin)) { // 执行管理操作 } if (subject.isPermitted(user:delete)) { // 删除用户 }注解式授权RequiresRoles(admin) public void deleteUser(User user) { // 只有admin角色可以调用此方法 }标签式授权JSP/GSPshiro:hasRole nameadmin a href/adminAdmin Panel/a /shiro:hasRole4.2 授权流程源码分析Shiro的授权流程同样经过多个组件授权检查入口// AuthorizingSecurityManager.java public void checkPermission(PrincipalCollection principals, String permission) { this.authorizer.checkPermission(principals, permission); }ModularRealmAuthorizer处理// ModularRealmAuthorizer.java public void checkPermission(PrincipalCollection principals, String permission) { assertRealmsConfigured(); for (Realm realm : getRealms()) { if (realm instanceof Authorizer) { ((Authorizer) realm).checkPermission(principals, permission); } } }Realm授权实现// AuthorizingRealm.java public void checkPermission(PrincipalCollection principals, String permission) { AuthorizationInfo info getAuthorizationInfo(principals); checkPermission(permission, info); }4.3 权限字符串设计Shiro的权限字符串通常采用资源:操作:实例的格式基本权限user:create - 创建用户的权限user:delete - 删除用户的权限实例级权限user:edit:123 - 编辑ID为123的用户的权限通配符权限user:* - 所有用户操作权限*:view - 查看所有资源的权限自定义权限解析public class MyPermissionResolver implements PermissionResolver { Override public Permission resolvePermission(String permissionString) { return new MyWildcardPermission(permissionString); } } // 配置权限解析器 securityManager.setPermissionResolver(new MyPermissionResolver());5. 实际应用与最佳实践5.1 集成Spring Boot在Spring Boot中集成Shiro的步骤添加依赖dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring-boot-starter/artifactId version1.8.0/version /dependency配置ShiroConfiguration public class ShiroConfig { Bean public Realm realm() { MyRealm realm new MyRealm(); realm.setCredentialsMatcher(hashedCredentialsMatcher()); return realm; } Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher matcher new HashedCredentialsMatcher(); matcher.setHashAlgorithmName(SHA-256); matcher.setHashIterations(1024); return matcher; } Bean public SecurityManager securityManager(Realm realm) { DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } }5.2 缓存策略优化Shiro的缓存机制可以显著提高性能启用缓存// 配置缓存管理器 CacheManager cacheManager new EhCacheManager(); securityManager.setCacheManager(cacheManager); // 在Realm中启用缓存 realm.setAuthenticationCachingEnabled(true); realm.setAuthorizationCachingEnabled(true);缓存策略认证缓存缓存用户凭证信息授权缓存缓存用户权限信息缓存失效// 当用户权限变更时清除缓存 public void clearAuthorizationCache(String username) { SimplePrincipalCollection principals new SimplePrincipalCollection(username, realm.getName()); realm.clearCachedAuthorizationInfo(principals); }5.3 常见问题与解决方案认证失败但无异常信息检查Realm的doGetAuthenticationInfo方法是否返回了正确的AuthenticationInfo确保CredentialsMatcher配置正确授权缓存不更新调用realm.clearCachedAuthorizationInfo()清除缓存设置合理的缓存过期时间RememberMe功能失效检查Cookie配置是否正确确保RememberMe管理器已正确配置Session管理问题// 配置Session管理器 DefaultWebSessionManager sessionManager new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(1800000); // 30分钟 securityManager.setSessionManager(sessionManager);性能优化建议使用缓存减少数据库查询合理设计权限字符串避免过于复杂的权限检查对于频繁的权限检查考虑使用RequiresPermissions注解而非编程式检查6. 安全增强与扩展6.1 防止会话固定攻击Shiro提供了会话固定攻击防护Bean public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager new DefaultWebSessionManager(); sessionManager.setSessionIdUrlRewritingEnabled(false); // 禁用URL重写 sessionManager.setSessionIdCookieEnabled(true); sessionManager.setDeleteInvalidSessions(true); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionIdCookie(new SimpleCookie(SHRIOSESSIONID)); return sessionManager; }6.2 多Realm策略Shiro支持配置多个Realm并指定认证策略Bean public ModularRealmAuthenticator authenticator() { ModularRealmAuthenticator authenticator new ModularRealmAuthenticator(); authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy()); return authenticator; } Bean public SecurityManager securityManager(Realm realm1, Realm realm2) { DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setAuthenticator(authenticator()); securityManager.setRealms(Arrays.asList(realm1, realm2)); return securityManager; }6.3 自定义Filter扩展Shiro的Filter机制允许自定义安全控制public class MyCustomFilter extends AccessControlFilter { Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { // 自定义访问控制逻辑 return true; } Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { // 访问被拒绝时的处理 return false; } } // 配置Filter MapString, Filter filters new HashMap(); filters.put(custom, new MyCustomFilter()); shiroFilterFactoryBean.setFilters(filters);6.4 分布式会话支持在分布式环境中使用ShiroBean public SessionDAO sessionDAO() { RedisSessionDAO sessionDAO new RedisSessionDAO(); sessionDAO.setRedisManager(redisManager()); return sessionDAO; } Bean public SessionManager sessionManager(SessionDAO sessionDAO) { DefaultWebSessionManager sessionManager new DefaultWebSessionManager(); sessionManager.setSessionDAO(sessionDAO); return sessionManager; }

相关新闻

信号与槽的介绍

信号与槽的介绍

1.信号和槽概述qt中谈到信号,涉及到三个要素:1.信号源:由哪个控件发出信号。2.信号的类型:用户进行不同的操作就可能触发不同的信号(点击按钮触发点击信号、在输入框中移到光标触发移到光标的信号等)。3.信号的处理方式&#xff1…

2026/10/17 23:12:36 阅读更多 →
Qwen3.6-27B模型在5060Ti与V100显卡上的推理性能对比

Qwen3.6-27B模型在5060Ti与V100显卡上的推理性能对比

1. 项目背景与测试目标最近在本地大模型推理领域,Qwen3.6-27B这款开源模型因其优秀的性能表现获得了广泛关注。作为一名长期关注AI推理硬件选型的从业者,我决定对两款主流显卡——NVIDIA 5060Ti 16G和V100 32G进行实测对比,看看在Qwen3.6-27B…

2026/10/18 11:24:00 阅读更多 →
在线教育平台的 AI 代码生成实践:课件页面模板化与质量保障体系

在线教育平台的 AI 代码生成实践:课件页面模板化与质量保障体系

在线教育平台的 AI 代码生成实践:课件页面模板化与质量保障体系 在线教育平台的课件页面开发,长期面临两个核心矛盾:一是课件数量大、迭代快,手工编写页面效率不足;二是课件质量参差不齐,缺少统一的代码规范…

2026/10/19 19:09:31 阅读更多 →

最新新闻

深入解析上下文模式:从参数透传到架构级上下文管理

深入解析上下文模式:从参数透传到架构级上下文管理

1. 从"上下文模式"说起:一个被低估的架构决策第一次看到"context-mode"这个词,很多人会下意识地把它归类成某个框架里的配置项,或者某个API的一个参数枚举值。但如果你真正在工程一线待过几年,就会明白&#…

2026/10/20 15:31:21 阅读更多 →
部落竞争与成员合作算法(CTCM)实现无人机城市三维避障航迹规划

部落竞争与成员合作算法(CTCM)实现无人机城市三维避障航迹规划

楼宇之间穿行这件事,我在之前的项目里吃过大亏。当时用的是二维平面路径规划,无人机飞着飞着就撞上了高层建筑的侧立面——原因很简单,二维路径只考虑水平面的躲避,根本没算高楼在不同高度层的“投影范围”,更没考虑爬…

2026/10/20 15:31:21 阅读更多 →
CANOCO 5.0 PCA分析完全指南:从数据导入到排序图解读

CANOCO 5.0 PCA分析完全指南:从数据导入到排序图解读

简介:CANOCO 5.0 是一款面向生态学与植物群落研究者的专业排序分析工具,主要用于 PCA、对应分析等多元统计,帮助将样方或植物种排列在特定空间中,使排序轴反映生态梯度,进而解释植被分布与环境因子之间的连续关系。对于…

2026/10/20 15:31:21 阅读更多 →
附合导线与四等水准平差表格的Excel自动生成实战

附合导线与四等水准平差表格的Excel自动生成实战

做测量最烦的从来不是外业晒大太阳,而是内业排表。上周刚交完一个项目的测量资料,一条附合导线带四个转点,一段约三公里的四等水准路线,白天的数据其实测得很顺,到了晚上却卡在了表格上:角度闭合差、坐标增…

2026/10/20 15:31:21 阅读更多 →
基于单片机的红外测距仪:从光电转换到查表标定全解析

基于单片机的红外测距仪:从光电转换到查表标定全解析

红外测距仪这名字听着唬人,其实拆开看就是两件事:用红外光“摸”一下目标有多远,再把距离显示出来。最近帮A同学捋一套基于单片机的红外测距仪设计,从原理图到代码再到标定整体过了一遍,发现这东西对入门的价值被严重低…

2026/10/20 15:31:21 阅读更多 →
WebSocket断线重连实战:心跳机制、指数退避与消息补偿方案

WebSocket断线重连实战:心跳机制、指数退避与消息补偿方案

做个长连接项目,断线重连这关早晚要过。我见过不少团队,连接正常时觉得一切都很简单,直到某天用户反馈“消息发不出去”“聊天记录中间断了一截”,才意识到WebSocket的稳定性问题才是整个项目的分水岭。这篇文章不打算从握手细节讲…

2026/10/20 15:30:20 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →