当前位置: 首页 > news >正文

别再乱配Shiro了!Spring Boot整合Shiro实现Token登录,这份配置清单请收好

Spring Boot与Shiro的Token认证实践指南

在当今的Web应用开发中,认证与授权机制是保障系统安全的核心组件。许多开发者选择Apache Shiro作为安全框架,但在与Spring Boot整合时,尤其是采用Token认证模式时,常常会遇到各种配置难题。本文将系统性地梳理Spring Boot整合Shiro实现Token认证的关键配置点,帮助开发者避开常见陷阱。

1. 基础环境搭建

在开始配置之前,我们需要确保项目基础环境正确搭建。创建一个新的Spring Boot项目,并添加以下核心依赖:

<dependencies> <!-- Spring Boot Starter Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Apache Shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.9.0</version> </dependency> <!-- JWT支持(可选) --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> </dependencies>

关键配置检查清单

  • 确保Shiro版本与Spring Boot版本兼容
  • 如果使用JWT,选择合适的JWT库版本
  • 检查依赖冲突,特别是与Spring Security的冲突

2. Shiro核心配置详解

Shiro的核心配置主要集中在ShiroConfig类中,这个类需要包含以下几个关键Bean的定义:

@Configuration public class ShiroConfig { @Bean public SecurityManager securityManager(CustomRealm customRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(customRealm); securityManager.setSessionManager(sessionManager()); return securityManager; } @Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionIdUrlRewritingEnabled(false); return sessionManager; } @Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); // 配置自定义过滤器 Map<String, Filter> filters = new HashMap<>(); filters.put("tokenAuth", new TokenAuthenticationFilter()); shiroFilter.setFilters(filters); // 配置拦截规则 Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/api/login", "anon"); filterMap.put("/api/public/**", "anon"); filterMap.put("/api/**", "tokenAuth"); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; } }

关键点解析

配置项说明常见问题
SecurityManagerShiro安全核心必须正确设置Realm和SessionManager
SessionManager会话管理禁用URL重写可提高安全性
ShiroFilterFactoryBean请求过滤拦截规则顺序很重要

3. 自定义Token认证实现

Token认证的核心在于自定义Realm和Filter。以下是实现Token认证的关键组件:

3.1 自定义Realm实现

public class CustomRealm extends AuthorizingRealm { @Override public boolean supports(AuthenticationToken token) { return token instanceof JwtToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 添加角色和权限 info.addRoles(getRolesForUser(username)); info.addStringPermissions(getPermissionsForUser(username)); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { JwtToken jwtToken = (JwtToken) token; String jwt = (String) jwtToken.getCredentials(); // 验证JWT有效性 if (!validateToken(jwt)) { throw new AuthenticationException("Invalid token"); } String username = extractUsernameFromToken(jwt); return new SimpleAuthenticationInfo(username, jwt, getName()); } }

3.2 自定义Token过滤器

public class TokenAuthenticationFilter extends AuthenticatingFilter { @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { HttpServletRequest httpRequest = (HttpServletRequest) request; String token = httpRequest.getHeader("Authorization"); if (token == null || !token.startsWith("Bearer ")) { return null; } return new JwtToken(token.substring(7)); } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { if (executeLogin(request, response)) { return true; } ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED); return false; } }

Token处理流程

  1. 客户端发送请求,携带Token
  2. 过滤器提取Token并创建认证Token
  3. Shiro调用Realm进行认证
  4. 认证成功后,进行授权检查
  5. 请求继续处理或返回错误

4. 登录与Token生成

登录接口需要生成Token并返回给客户端:

@RestController @RequestMapping("/api") public class AuthController { @PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginRequest request) { // 验证用户名密码 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken( request.getUsername(), request.getPassword() ); try { subject.login(token); // 生成JWT String jwtToken = Jwts.builder() .setSubject(request.getUsername()) .setExpiration(new Date(System.currentTimeMillis() + 3600000)) .signWith(SignatureAlgorithm.HS512, "secretKey") .compact(); return ResponseEntity.ok(new AuthResponse(jwtToken)); } catch (AuthenticationException e) { return ResponseEntity.status(401).body("Invalid credentials"); } } }

Token生成最佳实践

  • 设置合理的过期时间
  • 使用安全的签名算法
  • 不要在Token中存储敏感信息
  • 考虑使用Refresh Token机制

5. 高级配置与优化

5.1 集群环境支持

在集群环境中,需要考虑Session共享问题。可以通过以下方式实现:

@Bean @ConditionalOnProperty(name = "cluster.enabled", havingValue = "true") public SessionManager clusterSessionManager(RedisTemplate<String, Object> redisTemplate) { RedisSessionDAO sessionDAO = new RedisSessionDAO(); sessionDAO.setRedisTemplate(redisTemplate); DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setSessionDAO(sessionDAO); return sessionManager; }

5.2 性能优化

对于高并发场景,可以考虑以下优化措施:

  1. 缓存授权信息:在Realm中实现缓存机制
  2. Token黑名单:实现Token失效机制
  3. 异步验证:对于耗时操作采用异步方式
@Bean public CacheManager shiroCacheManager(RedisTemplate<String, Object> redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(); cacheManager.setRedisTemplate(redisTemplate); return cacheManager; } @Bean public SecurityManager securityManager(CustomRealm customRealm, CacheManager cacheManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(customRealm); securityManager.setCacheManager(cacheManager); return securityManager; }

6. 常见问题排查

在实际项目中,经常会遇到以下问题:

  1. Filter不生效

    • 检查Filter是否注册到ShiroFilterFactoryBean
    • 确认拦截规则配置正确
  2. 依赖注入失败

    • 确保Filter是通过ShiroFilterFactoryBean注册
    • 考虑使用静态方法获取Bean
  3. 跨域问题

    • 确保CORS配置在Shiro过滤器之前执行
    • 在Filter中正确处理OPTIONS请求
public class TokenAuthenticationFilter extends AuthenticatingFilter { @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { return true; } return super.isAccessAllowed(request, response, mappedValue); } }

在实际项目中整合Spring Boot和Shiro实现Token认证时,关键是要理解各个组件的职责和交互方式。通过本文提供的配置清单和最佳实践,开发者可以快速搭建安全可靠的认证系统,同时避免常见的配置错误。

http://www.jsqmd.com/news/647171/

相关文章:

  • Stata17新版实测:3种数据导入方法速度对比(附命令行自动化脚本)
  • Renesas MCU开发踩坑记:CS+ for CC找不到iodefine.h的3种解决方法
  • 2025届毕业生推荐的AI科研助手推荐
  • aubo i5 + realsense D435i手眼标定
  • 想把 Chrome 插件变成独立的桌面程序
  • 2025届最火的十大降AI率工具推荐
  • 音视频直播构建优化
  • 保姆级教程:用Python+Ultralytics YOLOv8实时识别你电脑屏幕上的任何物体(附完整代码)
  • 2026年4月企业微信SCRM系统TOP7实测榜单:全行业私域增长工具选购指南
  • 官宣!数数科技正式更名为 ThinkingAI
  • P1618三连击 (暴力+枚举)
  • 顶级域名的投资策略——为什么要投资外国域名
  • 字符串处理的艺术:R语言中的正则表达式
  • 3步解决Windows软件乱码问题:Locale Emulator区域模拟终极方案
  • 回流APP正规吗?20亿+成交硬核见证,制度护航打造可信翡翠交易平台
  • tomcat乱码
  • 深入解析Bezier曲线的导矢计算与de Casteljau算法的几何关联
  • 活动抽奖系统--测试报告
  • NoteWidget:让OneNote支持Markdown的终极指南,快速提升技术笔记效率80%
  • BilibiliDown终极指南:如何轻松批量下载B站视频并建立个人视频库
  • 为什么92%的AI团队还在用VQA 1.x?2026奇点大会宣布VQA 3.0强制兼容期仅剩180天!
  • 解决Spring应用中的环境变量配置问题
  • 【架构实战】告别“黑盒”调试:影刀RPA开发多浏览器并发 实现店群自动化RPA 系统中的可观测性与全链路监控设计
  • 【2026 职场洗牌系列 16】 行政后勤的困局:当“隐形劳动”被算法看见并替代
  • 关闭谷歌浏览器(Google Chrome)自动更新方法
  • Magika:文件类型检测小模型
  • 冰雪传奇点卡重制版纯月卡公平生态:无VIP装备全靠打经解析
  • 可解释性不是附加功能,而是合规刚需:欧盟AI Act生效倒计时下,多模态模型必须通过的4层可追溯性验证(含审计模板)
  • SQL中的聚合函数与GROUP BY的配合使用
  • WPF 打造工业级图像控件:支持海康相机与 ROI 框选