Shiro权限框架整合Spring配置全解析
本文详细解读了如何将Apache Shiro权限框架与Spring框架进行无缝整合,打造安全可靠的应用系统。从添加Maven依赖开始,逐步讲解了自定义Realm的创建,包括身份验证(AuthenticationInfo)和授权(AuthorizationInfo)的实现,以及SecurityManager的配置。重点介绍了ShiroFilterFactoryBean的使用,通过设置URL拦截规则,实现灵活的权限控制。此外,还深入探讨了在Spring Boot中启用Shiro的方法,以及利用`@RequiresRoles`和`@RequiresPermissions`注解进行权限控制。文章还针对分布式环境下的Session共享问题,提供了Shiro自带Session管理、Spring Session以及第三方方案等多种解决方案。最后,还介绍了如何通过集成CAS或自定义OAuth 2.0协议实现单点登录(SSO),以及如何自定义认证流程,例如增加验证码校验等功能,助力开发者构建更安全、更灵活的Spring应用。
Shiro整合Spring的核心在于通过配置将Shiro的安全管理功能嵌入Spring应用上下文中。1. 添加Maven依赖,包括shiro-spring、spring-context、spring-beans、spring-web及日志组件;2. 创建自定义Realm类继承AuthorizingRealm,实现doGetAuthorizationInfo和doGetAuthenticationInfo方法;3. 配置ShiroConfig类,定义MyRealm、SecurityManager、ShiroFilterFactoryBean等Bean,并设置URL拦截规则和权限控制支持;4. 在Spring Boot启动类中启用Shiro;5. 使用@RequiresRoles或@RequiresPermissions注解实现权限控制;6. 分布式环境下处理Session共享可通过Shiro自带Session管理、Spring Session或第三方方案如Redis实现;7. 实现SSO可通过集成CAS或自定义OAuth 2.0协议;8. 自定义认证流程需创建自定义AuthenticationToken和Realm,并在认证方法中添加额外校验逻辑如验证码验证。

Shiro整合Spring,核心在于将Shiro的安全管理功能无缝嵌入到Spring的应用上下文中,实现权限控制、认证和授权等功能。这需要配置Shiro的各种组件,并让Spring管理它们的生命周期。

解决方案
添加Maven依赖: 首先,在你的
pom.xml文件中添加Shiro和Spring相关的依赖。
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.9.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.23</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.3.23</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.23</version> </dependency> <!-- 引入slf4j日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.36</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> </dependency>版本号根据实际情况调整,Spring Web依赖主要用于Web应用。
配置Shiro的Realm: Realm是Shiro用于获取用户身份验证和授权信息的组件。你需要创建一个Realm实现类,并配置它。

public class MyRealm extends AuthorizingRealm { @Autowired private UserService userService; // 假设你有一个UserService @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); User user = userService.findByUsername(username); // 从数据库获取用户 if (user == null) { return null; } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // 添加角色 user.getRoles().forEach(role -> authorizationInfo.addRole(role.getName())); //添加权限 user.getPermissions().forEach(permission -> authorizationInfo.addStringPermission(permission.getName())); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); User user = userService.findByUsername(username); // 从数据库获取用户 if (user == null) { return null; // 用户不存在 } return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName()); } }这里假设你有一个
UserService用于从数据库获取用户信息。注意,密码通常需要进行加密存储,并使用Shiro提供的加密工具类进行验证。配置Shiro的SecurityManager:
SecurityManager是Shiro的核心组件,用于管理所有的Subject,并协调认证和授权。@Configuration public class ShiroConfig { @Bean public MyRealm myRealm() { return new MyRealm(); } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myRealm()); return securityManager; } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager 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); shiroFilterFactoryBean.setLoginUrl("/login"); // 未认证跳转URL shiroFilterFactoryBean.setSuccessUrl("/index"); // 认证成功URL shiroFilterFactoryBean.setUnauthorizedUrl("/403"); // 未授权URL return shiroFilterFactoryBean; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } }这个配置类定义了Shiro的Realm、SecurityManager和ShiroFilterFactoryBean。
ShiroFilterFactoryBean定义了URL的拦截规则。AuthorizationAttributeSourceAdvisor和DefaultAdvisorAutoProxyCreator用于支持基于注解的权限控制。LifecycleBeanPostProcessor用于管理Shiro Bean的生命周期。注意@DependsOn注解,确保lifecycleBeanPostProcessor先被创建。在Spring Boot启动类中启用Shiro:
@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }Spring Boot会自动扫描并加载Shiro的配置。
使用Shiro的注解: 你可以在Controller中使用Shiro的注解来控制权限。
@Controller public class MyController { @RequiresRoles("admin") @RequestMapping("/admin") public String adminPage() { return "admin"; } @RequiresPermissions("user:create") @RequestMapping("/user/create") public String createUser() { return "createUser"; } }@RequiresRoles用于限制只有具有特定角色的用户才能访问,@RequiresPermissions用于限制只有具有特定权限的用户才能访问。
Shiro整合Spring后,如何处理session共享问题?
Shiro默认使用Servlet容器的Session管理,但在分布式环境下,Servlet容器的Session无法共享。解决这个问题有几种方法:
- 使用Shiro自带的Session管理: Shiro可以自己管理Session,你需要配置一个
SessionDAO用于Session的持久化,例如使用Redis或数据库存储Session。 - 使用Spring Session: Spring Session提供了一种统一的Session管理方案,可以与Shiro集成。你需要引入Spring Session的依赖,并配置Session的存储方式。
- 使用第三方Session共享方案: 例如使用Redis Session共享等。
使用Shiro进行单点登录(SSO)如何配置?
Shiro本身不直接提供SSO功能,但可以与其他SSO方案集成。一种常见的做法是:
- 集成CAS (Central Authentication Service): CAS是一种流行的开源SSO解决方案。你需要配置Shiro使用CAS的客户端,将用户的认证委托给CAS服务器。
- 自定义SSO集成: 你也可以自定义SSO集成,例如通过OAuth 2.0协议与其他认证服务器交互。这需要实现自定义的Realm,用于从认证服务器获取用户信息。
如何自定义Shiro的认证流程,例如增加验证码校验?
自定义Shiro的认证流程通常需要以下步骤:
- 自定义AuthenticationToken: 创建一个自定义的
AuthenticationToken,用于携带验证码等额外信息。 - 自定义Realm: 在自定义的Realm中,重写
doGetAuthenticationInfo方法,从AuthenticationToken中获取验证码,并进行校验。如果验证码校验失败,抛出自定义的异常。 - 配置ShiroFilterFactoryBean: 在
ShiroFilterFactoryBean中,配置自定义的认证过滤器,用于处理认证流程。
在doGetAuthenticationInfo中,你需要先验证验证码,如果验证码正确,再进行用户身份验证。示例代码:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
MyAuthenticationToken myToken = (MyAuthenticationToken) token;
String username = (String) myToken.getPrincipal();
String captcha = myToken.getCaptcha();
// 验证验证码
if (!validateCaptcha(captcha)) {
throw new IncorrectCaptchaException("验证码错误");
}
User user = userService.findByUsername(username);
if (user == null) {
return null; // 用户不存在
}
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
}注意,IncorrectCaptchaException需要你自定义。同时,MyAuthenticationToken也需要你自定义,继承自AuthenticationToken,并添加captcha属性。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。
GuavaCache使用教程:Java缓存实现详解
- 上一篇
- GuavaCache使用教程:Java缓存实现详解
- 下一篇
- Python操作Neo4j:py2neo图数据库入门指南
-
- 文章 · java教程 | 6分钟前 |
- JavaStream递归扁平化数组技巧
- 391浏览 收藏
-
- 文章 · java教程 | 21分钟前 | completablefuture thenApply thenCompose 异步链式调用 supplyAsync
- Java异步链式调用实现技巧
- 377浏览 收藏
-
- 文章 · java教程 | 37分钟前 |
- Java对象属性私有化技巧解析
- 239浏览 收藏
-
- 文章 · java教程 | 49分钟前 |
- Java生成二维码:ZXing库使用教程
- 275浏览 收藏
-
- 文章 · java教程 | 57分钟前 |
- Java类库扩展设计实战教程
- 229浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- SLF4J日志空参数报错怎么解决
- 133浏览 收藏
-
- 文章 · java教程 | 1小时前 | java 序列化 浅拷贝 深拷贝 Cloneable接口
- Java对象深浅拷贝怎么实现?
- 269浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- Java多态实现与调用详解
- 395浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- Java异常处理提升程序稳定性方法解析
- 254浏览 收藏
-
- 文章 · java教程 | 1小时前 | java 负载均衡 面向对象 任务分配系统 TaskManager
- Java开发任务分配系统教程详解
- 369浏览 收藏
-
- 文章 · java教程 | 1小时前 | 设计模式 errorCode BaseException @ControllerAdvice 统一异常处理
- Java异常处理设计模式全解析
- 129浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java接口定义与实现示例详解
- 180浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3202次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3415次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3445次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4553次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3823次使用
-
- 提升Java功能开发效率的有力工具:微服务架构
- 2023-10-06 501浏览
-
- 掌握Java海康SDK二次开发的必备技巧
- 2023-10-01 501浏览
-
- 如何使用java实现桶排序算法
- 2023-10-03 501浏览
-
- Java开发实战经验:如何优化开发逻辑
- 2023-10-31 501浏览
-
- 如何使用Java中的Math.max()方法比较两个数的大小?
- 2023-11-18 501浏览

