ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot3集成Shiro实现安全认证与授权

SpringBoot3集成Shiro实现安全认证与授权 1. SpringBoot3与Shiro集成概述在Java企业级应用开发中安全框架的选择直接影响系统的防护能力。Apache Shiro作为轻量级安全框架以其简洁的API和全面的安全功能受到开发者青睐。而SpringBoot3作为当前最新的SpringBoot大版本带来了诸多新特性。将两者结合既能享受SpringBoot的便捷又能获得Shiro强大的安全控制。我最近在一个电商后台管理系统中实践了SpringBoot3与Shiro的集成方案发现相比传统Spring SecurityShiro的配置更加直观学习曲线更平缓。特别是对于需要快速上线的项目Shiro的开箱即用特性可以节省大量开发时间。2. 环境准备与基础配置2.1 依赖引入首先需要在pom.xml中添加必要的依赖dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring-boot-starter/artifactId version1.11.0/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency注意SpringBoot3要求Java17环境而Shiro1.11.0版本已完全兼容SpringBoot3。如果使用旧版Shiro可能会出现兼容性问题。2.2 基础配置类创建Shiro的核心配置类Configuration public class ShiroConfig { Bean public ShiroFilterFactoryBean shiroFilterFactoryBean( DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); // 设置登录URL factoryBean.setLoginUrl(/login); // 设置未授权跳转URL factoryBean.setUnauthorizedUrl(/403); // 配置拦截规则 MapString, String filterChainDefinitionMap new LinkedHashMap(); filterChainDefinitionMap.put(/static/**, anon); filterChainDefinitionMap.put(/login, anon); filterChainDefinitionMap.put(/**, authc); factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return factoryBean; } Bean public DefaultWebSecurityManager securityManager(Realm realm) { DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } }3. 认证与授权实现3.1 自定义Realm开发Realm是Shiro的核心组件负责实际的认证和授权逻辑public class CustomRealm extends AuthorizingRealm { Autowired private UserService userService; // 授权逻辑 Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo new SimpleAuthorizationInfo(); // 从数据库获取角色和权限 SetString roles userService.findRoles(username); SetString permissions userService.findPermissions(username); authorizationInfo.setRoles(roles); authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } // 认证逻辑 Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { String username (String) token.getPrincipal(); User user userService.findByUsername(username); if (user null) { throw new UnknownAccountException(用户不存在); } if (user.getLocked()) { throw new LockedAccountException(账号已锁定); } return new SimpleAuthenticationInfo( user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName()); } }3.2 密码加密配置Shiro推荐使用加密存储密码避免明文存储的安全风险Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher matcher new HashedCredentialsMatcher(); matcher.setHashAlgorithmName(SHA-256); matcher.setHashIterations(1024); matcher.setStoredCredentialsHexEncoded(false); return matcher; } Bean public Realm realm() { CustomRealm realm new CustomRealm(); realm.setCredentialsMatcher(hashedCredentialsMatcher()); return realm; }4. 高级功能实现4.1 会话管理Shiro提供了完善的会话管理功能Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager new DefaultWebSessionManager(); // 设置会话超时时间毫秒 sessionManager.setGlobalSessionTimeout(1800000); // 删除无效session sessionManager.setDeleteInvalidSessions(true); // 定时检查session sessionManager.setSessionValidationSchedulerEnabled(true); return sessionManager; } // 在securityManager中注入 Bean public DefaultWebSecurityManager securityManager(Realm realm, SessionManager sessionManager) { DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setRealm(realm); securityManager.setSessionManager(sessionManager); return securityManager; }4.2 记住我功能实现记住我功能可以提升用户体验Bean public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager rememberMeManager new CookieRememberMeManager(); rememberMeManager.setCipherKey(Base64.decode(yourBase64EncodedKeyHere)); SimpleCookie cookie new SimpleCookie(rememberMe); cookie.setHttpOnly(true); cookie.setMaxAge(2592000); // 30天 rememberMeManager.setCookie(cookie); return rememberMeManager; } // 在ShiroFilterFactoryBean中添加filter filterChainDefinitionMap.put(/home, user); filterChainDefinitionMap.put(/**, authc);5. 安全防护与最佳实践5.1 防止Shiro反序列化漏洞Shiro历史上存在反序列化漏洞必须采取防护措施Bean public RememberMeManager rememberMeManager() { CookieRememberMeManager manager new CookieRememberMeManager(); // 必须设置自定义密钥不要使用默认密钥 manager.setCipherKey(yourCustomKeyHere.getBytes(StandardCharsets.UTF_8)); return manager; }5.2 性能优化建议缓存配置Shiro的授权信息应该缓存Bean public CacheManager cacheManager() { return new MemoryConstrainedCacheManager(); // 生产环境建议使用Redis等分布式缓存 } Bean public Realm realm() { CustomRealm realm new CustomRealm(); realm.setCacheManager(cacheManager()); realm.setCachingEnabled(true); realm.setAuthenticationCachingEnabled(true); realm.setAuthenticationCacheName(authenticationCache); realm.setAuthorizationCachingEnabled(true); realm.setAuthorizationCacheName(authorizationCache); return realm; }减少授权检查次数对于频繁访问的接口可以使用注解缓存权限验证结果RequiresPermissions(user:view) GetMapping(/users) public ListUser listUsers() { // ... }6. 常见问题排查6.1 登录失败无错误提示问题现象登录失败但页面没有显示错误信息。解决方案检查Shiro配置中是否设置了loginUrl确保登录页面有错误显示逻辑span th:if${shiroLoginFailure ! null} th:text${shiroLoginFailure}/span6.2 权限注解不生效问题现象在Controller方法上添加RequiresRoles等注解无效。解决方案确保在Spring配置中启用了Shiro注解Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor( DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; }确保在启动类上添加EnableAspectJAutoProxy6.3 会话失效问题问题现象用户会话意外失效。排查步骤检查session超时时间配置检查服务器是否重启导致内存会话丢失生产环境建议配置持久化会话存储7. 实际项目中的经验分享在最近的项目中我们遇到了几个值得分享的问题动态权限控制对于需要动态变更权限的系统我们实现了数据库驱动的权限管理Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 每次授权都从数据库获取最新权限 refreshPermissionsFromDB(); // ... }分布式会话在微服务架构下我们整合了Shiro与Spring SessionBean public SessionManager sessionManager(RedisOperationsSessionRepository sessionRepository) { SpringSessionManager sessionManager new SpringSessionManager(); sessionManager.setSessionRepository(sessionRepository); return sessionManager; }JWT集成对于前后端分离项目我们扩展了Shiro支持JWT认证public class JWTFilter extends AuthenticatingFilter { // 实现JWT解析和认证逻辑 }提示在SpringBoot3中WebFlux逐渐成为主流但Shiro目前主要支持Servlet环境。如果需要响应式编程支持可以考虑Spring Security或等待Shiro的响应式版本。
返回列表