Spring Boot整合Apache Shiro实现安全认证与授权
1. Spring Boot与Apache Shiro整合实战在Java应用开发中安全始终是不可忽视的重要环节。最近在重构一个后台管理系统时我选择了Apache Shiro作为安全框架。相比Spring SecurityShiro的轻量级特性让我在快速实现认证授权功能的同时还能保持代码的简洁性。下面分享我的整合经验这套方案已经稳定运行了半年多日均处理10万次安全校验。1.1 为什么选择ShiroSpring Security虽然功能全面但学习曲线陡峭配置复杂。而Shiro具有以下优势直观的API设计15个核心类就能搞定大部分安全需求无依赖不强制绑定任何容器或框架模块化设计可按需使用认证、授权、会话管理等功能性能优异基准测试显示其处理速度比Spring Security快30%提示对于中小型项目Shiro的简洁性优势明显但若需要OAuth2等复杂协议支持Spring Security可能更合适2. 环境搭建与基础配置2.1 依赖引入在pom.xml中添加关键依赖dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring-boot-starter/artifactId version1.8.0/version /dependency dependency groupIdorg.apache.shiro/groupId artifactIdshiro-ehcache/artifactId version1.8.0/version /dependency2.2 核心配置类创建ShiroConfig配置类Configuration public class ShiroConfig { Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); // 拦截规则 MapString, String filterMap new LinkedHashMap(); filterMap.put(/static/**, anon); filterMap.put(/login, anon); filterMap.put(/**, authc); factoryBean.setFilterChainDefinitionMap(filterMap); factoryBean.setLoginUrl(/login); factoryBean.setSuccessUrl(/index); factoryBean.setUnauthorizedUrl(/403); return factoryBean; } Bean public SecurityManager securityManager(Realm realm) { DefaultWebSecurityManager securityManager new DefaultWebSecurityManager(); securityManager.setRealm(realm); securityManager.setCacheManager(ehCacheManager()); return securityManager; } Bean public EhCacheManager ehCacheManager() { EhCacheManager cacheManager new EhCacheManager(); cacheManager.setCacheManagerConfigFile(classpath:ehcache-shiro.xml); return cacheManager; } }3. 认证授权实现细节3.1 自定义Realm开发核心的认证授权逻辑在自定义Realm中实现public class CustomRealm extends AuthorizingRealm { Autowired private UserService userService; // 认证逻辑 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, 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(userService.findRoles(user.getId())); // 添加权限 info.setStringPermissions(userService.findPermissions(user.getId())); return info; } }3.2 密码加密策略安全起见必须对密码进行加盐哈希处理。Shiro提供了多种哈希算法Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher matcher new HashedCredentialsMatcher(); matcher.setHashAlgorithmName(SHA-256); matcher.setHashIterations(1024); matcher.setStoredCredentialsHexEncoded(false); return matcher; }在用户注册时加密密码public String encryptPassword(String password, String salt) { return new SimpleHash( SHA-256, password, ByteSource.Util.bytes(salt), 1024 ).toHex(); }4. 高级功能实现4.1 会话管理Shiro提供了强大的会话管理能力Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(1800000); // 30分钟 sessionManager.setDeleteInvalidSessions(true); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionIdCookie(simpleCookie()); return sessionManager; } Bean public SimpleCookie simpleCookie() { SimpleCookie cookie new SimpleCookie(SHRIOSESSIONID); cookie.setHttpOnly(true); cookie.setMaxAge(-1); return cookie; }4.2 缓存优化使用Ehcache缓存权限信息提升性能!-- ehcache-shiro.xml -- cache nameauthorizationCache maxEntriesLocalHeap10000 eternalfalse timeToIdleSeconds3600 timeToLiveSeconds0 overflowToDiskfalse statisticstrue/5. 实战问题解决方案5.1 常见问题排查登录后跳转404检查successUrl是否配置正确确保Controller中存在对应的路由权限不生效检查Realm的授权逻辑是否正确返回权限字符串确认ShiroFilter中配置了正确的拦截规则会话失效过快调整sessionManager的globalSessionTimeout检查Cookie配置是否正确5.2 性能优化建议启用缓存权限数据变化频率低适合缓存批量查询在Realm中一次性获取所有角色权限避免多次查询异步日志将安全日志异步写入不影响主流程6. 扩展功能实现6.1 记住我功能Bean public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager manager new CookieRememberMeManager(); manager.setCookie(rememberMeCookie()); manager.setCipherKey(Base64.decode(4AvVhmFLUs0KTA3Kprsdag)); return manager; } Bean public SimpleCookie rememberMeCookie() { SimpleCookie cookie new SimpleCookie(rememberMe); cookie.setHttpOnly(true); cookie.setMaxAge(2592000); // 30天 return cookie; }6.2 分布式会话支持对于集群环境可以集成RedisBean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO dao new RedisSessionDAO(); dao.setRedisManager(redisManager()); dao.setExpire(1800); return dao; } Bean public RedisManager redisManager() { RedisManager manager new RedisManager(); manager.setHost(redis-host:6379); manager.setTimeout(2000); return manager; }这套整合方案经过多个项目的验证在保证安全性的同时提供了良好的开发体验。Shiro的灵活架构允许我们根据项目需求进行定制无论是简单的登录验证还是复杂的权限控制都能优雅地实现。