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/7/21 23:39:10 阅读更多 →
Qwen3.6-27B模型在5060Ti与V100显卡上的推理性能对比

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

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

2026/7/21 23:38:09 阅读更多 →
在线教育平台的 AI 代码生成实践:课件页面模板化与质量保障体系

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

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

2026/7/21 23:38:09 阅读更多 →

最新新闻

MSP430驱动ADS1293代码库解析:低功耗ECG设备开发实战

MSP430驱动ADS1293代码库解析:低功耗ECG设备开发实战

1. 项目概述与核心价值 在便携式医疗电子设备,尤其是心电图监测领域,开发者面临的核心挑战是如何在极致的功耗约束下,实现高精度、高可靠性的生物电信号采集与处理。这不仅仅是选对一颗低功耗的微控制器(MCU)和一颗高性…

2026/7/24 9:01:58 阅读更多 →
千笔AI写作与PaperRed论文工具对比测评

千笔AI写作与PaperRed论文工具对比测评

1. 论文写作工具现状与需求分析 在高等教育普及和终身学习理念深入人心的今天,论文写作已成为学术研究、职称评定和学历提升的必经之路。然而,面对繁重的写作任务,许多学习者常常陷入无从下手的困境。特别是自考学生群体,他们往往…

2026/7/24 9:01:58 阅读更多 →
RAG技术解析:大模型与知识库检索的完美结合

RAG技术解析:大模型与知识库检索的完美结合

1. RAG技术:当大模型遇上知识库检索 去年我在帮一家金融公司搭建智能客服系统时遇到了一个典型问题:他们的业务政策每周都在更新,但基于GPT-4的客服机器人总是给出过时的回答。直到我们引入RAG(检索增强生成)技术&…

2026/7/24 9:01:58 阅读更多 →
Unity自动寻路实战:从NavMesh烘焙到高级AI路径规划

Unity自动寻路实战:从NavMesh烘焙到高级AI路径规划

1. 项目概述:从零开始理解Unity的自动寻路在游戏开发里,让角色或NPC自己找到从A点到B点的路,是个再基础不过的需求。你肯定不想手动写一堆复杂的路径计算代码,那太费劲了。Unity引擎内置的Nav Mesh(导航网格&#xff0…

2026/7/24 9:01:58 阅读更多 →
LM96194硬件监控芯片:服务器系统稳定性的核心守护者

LM96194硬件监控芯片:服务器系统稳定性的核心守护者

1. 项目概述与芯片定位在服务器和工作站这类高性能计算设备的设计与维护中,系统稳定性是压倒一切的铁律。任何微小的电压波动或温度失控,都可能导致数据丢失、性能骤降甚至硬件永久性损坏。因此,一套能够实时、精准地“感知”系统健康状况&am…

2026/7/24 9:01:58 阅读更多 →
C++ STL stack容器适配器:从底层原理到实战应用与性能优化

C++ STL stack容器适配器:从底层原理到实战应用与性能优化

1. 项目概述:为什么C程序员必须掌握stack容器?如果你写过C,尤其是接触过算法题或者需要处理一些具有“后进先出”特性的数据,那你大概率听说过或者用过stack。但很多时候,我们只是把它当作一个“能用的工具”&#xff…

2026/7/24 9:00:58 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻