news 2026/9/12 6:47:49

Spring Security整合JWT与Redis实现高效认证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Security整合JWT与Redis实现高效认证

1. Spring Security与JWT、Redis整合方案概述

在现代Web应用开发中,权限认证是保障系统安全的核心环节。Spring Security作为Java生态中最成熟的安全框架,与JWT(JSON Web Token)的无状态认证机制以及Redis的高性能缓存特性相结合,能够构建出既安全又高效的认证授权体系。这套组合方案特别适合分布式系统和微服务架构,解决了传统Session管理在水平扩展时的痛点。

我曾在多个电商和金融项目中实践过这种架构,实测下来单系统可支撑10万+的QPS认证请求。与传统的Cookie-Session模式相比,JWT+Redis的方案减少了服务端存储压力,同时通过Redis的过期机制完美实现了令牌的黑名单管理。

2. 技术选型与核心组件解析

2.1 Spring Security的核心作用

Spring Security 5.7版本提供了完整的认证和授权能力链:

  • 认证流程:UsernamePasswordAuthenticationFilter处理登录请求
  • 授权控制:FilterSecurityInterceptor进行权限校验
  • 上下文管理:SecurityContextHolder存储当前用户安全上下文

关键配置类:

@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager())); } }

2.2 JWT的工作机制

JWT由三部分组成:

  1. Header:声明令牌类型和签名算法(如HS256)
  2. Payload:存储用户标识和自定义声明(如权限角色)
  3. Signature:对前两部分的签名验证

生成Token的典型代码:

public String generateToken(UserDetails userDetails) { Map<String, Object> claims = new HashMap<>(); claims.put("roles", userDetails.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toList())); return Jwts.builder() .setClaims(claims) .setSubject(userDetails.getUsername()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); }

2.3 Redis的增强功能

Redis在本方案中承担两个关键角色:

  1. 令牌黑名单:实现主动注销功能
  2. 用户权限缓存:减少数据库查询压力

典型数据结构设计:

  • Key设计:jwt:blacklist:<token指纹>,Value为过期时间戳
  • 权限缓存:user:perms:<username>存储序列化的权限集合

3. 完整实现流程详解

3.1 项目初始化配置

Maven依赖配置示例:

<dependencies> <!-- Spring Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- JWT支持 --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies>

3.2 认证过滤器实现

JwtAuthenticationFilter核心逻辑:

public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Override public Authentication attemptAuthentication( HttpServletRequest request, HttpServletResponse response) { try { LoginRequest creds = new ObjectMapper() .readValue(request.getInputStream(), LoginRequest.class); return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword(), new ArrayList<>()) ); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(...) { String token = jwtTokenUtil.generateToken(userDetails); response.addHeader("Authorization", "Bearer " + token); } }

3.3 授权过滤器设计

JwtAuthorizationFilter关键实现:

public class JwtAuthorizationFilter extends BasicAuthenticationFilter { @Override protected void doFilterInternal(...) { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith("Bearer ")) { chain.doFilter(request, response); return; } String token = header.replace("Bearer ", ""); if (redisTemplate.hasKey("jwt:blacklist:" + DigestUtils.md5DigestAsHex(token.getBytes()))) { response.sendError(HttpStatus.UNAUTHORIZED.value()); return; } UsernamePasswordAuthenticationToken authentication = getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); chain.doFilter(request, response); } }

3.4 Redis集成实现

令牌黑名单服务示例:

@Service public class TokenBlacklistService { @Autowired private RedisTemplate<String, String> redisTemplate; public void addToBlacklist(String token, long expiration) { String tokenKey = "jwt:blacklist:" + DigestUtils.md5DigestAsHex(token.getBytes()); redisTemplate.opsForValue().set( tokenKey, String.valueOf(System.currentTimeMillis()), Duration.ofMillis(expiration - System.currentTimeMillis()) ); } }

4. 高级特性与优化方案

4.1 令牌自动续签机制

通过双Token策略实现无感刷新:

  • Access Token:短期有效(如30分钟)
  • Refresh Token:长期有效(如7天),存储于HttpOnly Cookie

刷新流程:

@PostMapping("/token/refresh") public ResponseEntity<?> refreshToken(HttpServletRequest request) { String refreshToken = getRefreshTokenFromCookie(request); if (!jwtTokenUtil.validateToken(refreshToken)) { throw new InvalidTokenException("Refresh token invalid"); } String username = jwtTokenUtil.getUsernameFromToken(refreshToken); UserDetails userDetails = userDetailsService.loadUserByUsername(username); String newAccessToken = jwtTokenUtil.generateToken(userDetails); return ResponseEntity.ok(new TokenResponse(newAccessToken, refreshToken)); }

4.2 权限数据缓存策略

采用多级缓存提升性能:

  1. 本地Caffeine缓存:存储高频访问用户权限(5分钟过期)
  2. Redis缓存:全量用户权限数据(1小时过期)
  3. 数据库:权限数据持久层

缓存更新策略:

@CacheEvict(value = "user:perms", key = "#username") public void updateUserPermissions(String username) { // 更新数据库权限 // 清除Redis缓存会自动触发重新加载 }

5. 生产环境注意事项

5.1 安全加固措施

必须实施的防护策略:

  1. JWT签名密钥:至少使用HS512算法,密钥长度不小于64字符
  2. HTTPS强制:防止令牌在传输中被截获
  3. 令牌存储:前端应使用HttpOnly + Secure的Cookie或内存存储
  4. CSRF防护:对于非JWT的请求仍需启用CSRF保护

5.2 性能调优经验

Redis优化配置建议:

# Lettuce连接池配置 spring.redis.lettuce.pool.max-active=50 spring.redis.lettuce.pool.max-wait=1000ms spring.redis.lettuce.pool.max-idle=20 spring.redis.lettuce.pool.min-idle=5 # 集群模式下启用拓扑刷新 spring.redis.lettuce.cluster.refresh.adaptive=true spring.redis.lettuce.cluster.refresh.period=30s

5.3 监控与日志

关键监控指标:

  1. 认证成功率/失败率
  2. JWT解析耗时
  3. Redis操作延迟
  4. 黑名单命中率

日志记录建议:

@Slf4j public class JwtRequestLoggingFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(...) { long start = System.currentTimeMillis(); try { chain.doFilter(request, response); } finally { log.info("JWT request {} {} took {}ms", request.getMethod(), request.getRequestURI(), System.currentTimeMillis() - start); } } }

6. 常见问题排查指南

6.1 典型异常处理

异常现象可能原因解决方案
认证成功但后续请求401上下文未正确传递检查SecurityContextHolder设置
JWT解析失败签名不匹配或过期验证密钥一致性,检查时钟同步
Redis连接超时网络或配置问题检查连接池配置和网络连通性

6.2 跨域问题处理

Spring Security下的CORS配置:

@Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("https://domain.com")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); configuration.setAllowCredentials(true); configuration.addExposedHeader("Authorization"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }

6.3 集群部署注意事项

  1. 所有实例必须使用相同的JWT签名密钥
  2. Redis建议采用集群模式保证高可用
  3. 时钟同步:确保服务器时间误差在30秒内
  4. 负载均衡器需要透传Authorization头
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 6:44:48

DeepSpeed ZeRO优化器:大模型训练显存优化与性能调优

1. DeepSpeed ZeRO优化器&#xff1a;大模型训练的革命性加速方案在训练参数量超过10亿的大模型时&#xff0c;传统数据并行方法会遇到显存墙瓶颈——每个GPU需要存储完整的模型副本、优化器状态和梯度&#xff0c;导致显存迅速耗尽。微软开发的DeepSpeed框架中的ZeRO&#xff…

作者头像 李华
网站建设 2026/9/12 6:38:15

AI项目落地死亡谷:从实验室到战场的实战策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 6:36:57

vue-vben-admin 如何用权限码和角色实现按钮级细粒度权限控制

vue-vben-admin 如何用权限码和角色实现按钮级细粒度权限控制 【免费下载链接】vue-vben-admin A modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast! 项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin 在…

作者头像 李华