Header:采用HMAC SHA256算法示例{ "alg": "HS256", "typ": "JWT"}Payload:包含标准声明与业务扩展摘要:{ "sub": "user123", "iat": 1629098000, "exp": 1629101600, "roles": ["ROLE_ADMIN", "ROLE_USER"]}
json
{ "sub": "user123", "iat": 1629098000, "exp": 1629101600, "roles": ["ROLE_ADMIN", "ROLE_USER"]}Signature:基于密钥的哈希签名实现HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key)java
@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf.disable .sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and .addFilter(new JwtAuthenticationFilter(authenticationManager)) .addFilterAfter(new JwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class) .authorizeRequests .antMatchers("/auth/login").permitAll .anyRequest.authenticated; }}java
@Componentpublic class JwtProvider { private final String secret = "complex_secret_key_using_HS256"; private final long expiration = 3600000; // 1小时 public String generateToken(UserDetails userDetails) { Map claims = new HashMap; claims.put("roles", userDetails.getAuthorities.stream .map(GrantedAuthority::getAuthority) .collect(Collectors.toList)); return Jwts.builder .setClaims(claims) .setSubject(userDetails.getUsername) .setIssuedAt(new Date) .setExpiration(new Date(System.currentTimeMillis + expiration)) .signWith(SignatureAlgorithm.HS256, secret) .compact; } public boolean validateToken(String token) { try { Jwts.parser.setSigningKey(secret).parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { throw new InvalidJwtException("Expired or invalid JWT token"); } }}java
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final ObjectMapper objectMapper = new ObjectMapper; @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { try { LoginRequest loginRequest = objectMapper.readValue( request.getInputStream, LoginRequest.class); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( loginRequest.getUsername, loginRequest.getPassword); return getAuthenticationManager.authenticate(authRequest); } catch (IOException e) { throw new AuthenticationServiceException("Authentication failed"); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) { UserDetails userDetails = (UserDetails) authResult.getPrincipal; String token = jwtProvider.generateToken(userDetails); response.addHeader("Authorization", "Bearer " + token); }}java
public class JwtAuthorizationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) { String header = request.getHeader("Authorization"); if (header != null && header.startsWith("Bearer ")) { String token = header.replace("Bearer ", ""); if (jwtProvider.validateToken(token)) { Claims claims = jwtProvider.parseToken(token); List authorities = ((List) claims.get("roles")) .stream .map(role -> new SimpleGrantedAuthority((String) role)) .collect(Collectors.toList); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( claims.getSubject, null, authorities); SecurityContextHolder.getContext.setAuthentication(authentication); } } filterChain.doFilter(request, response); }}java
public class TokenRefreshService { @Value("${jwt.refreshExpiration}") private Long refreshExpiration; public TokenPair generateTokenPair(UserDetails userDetails) { String accessToken = jwtProvider.generateToken(userDetails); String refreshToken = Jwts.builder .setSubject(userDetails.getUsername) .setExpiration(new Date(System.currentTimeMillis + refreshExpiration)) .signWith(SignatureAlgorithm.HS512, refreshSecret) .compact; return new TokenPair(accessToken, refreshToken); } public String refreshAccessToken(String refreshToken) { Claims claims = validateRefreshToken(refreshToken); UserDetails userDetails = userService.loadUserByUsername(claims.getSubject); return jwtProvider.generateToken(userDetails); }}java
@Servicepublic class TokenBlacklistService { @Autowired private RedisTemplate redisTemplate; public void invalidateToken(String token) { Claims claims = jwtProvider.parseToken(token); long expiration = claims.getExpiration.getTime - System.currentTimeMillis; if (expiration > 0) { redisTemplate.opsForValue.set( "blacklist:" + token, "invalid", expiration, TimeUnit.MILLISECONDS); } } public boolean isTokenBlacklisted(String token) { return redisTemplate.hasKey("blacklist:" + token); }}java
@Beanpublic CorsFilter corsFilter { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource; CorsConfiguration config = new CorsConfiguration; config.setAllowCredentials(true); config.addAllowedOrigin("https://domain.com"); config.addAllowedHeader("*"); config.addExposedHeader("Authorization"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source);}java
@Configurationpublic class SessionControlConfig { @Bean public ConcurrentSessionControlAuthenticationStrategy sessionStrategy { ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry); strategy.setMaximumSessions(1); strategy.setExceptionIfMaximumExceeded(true); return strategy; } @Bean public SessionRegistry sessionRegistry { return new SessionRegistryImpl; }}通过深度整合Spring Security与JWT,开发者可以构建出既符合现代安全标准,又能支撑高并发场景的认证体系。建议在具体实施时,根据业务场景选择合适的令牌失效策略,并建立完善的监控告警机制。对于核心业务系统,建议结合生物特征认证等增强手段构建多因素认证方案。
来源:大龄程序猿小武
免责声明:本站系转载,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与本站联系,我们将在第一时间删除内容!