当前位置: 首页> 科技> 数码 > 东莞市路桥所_成都网站设计最加科技_免费软文推广平台_火狐搜索引擎

东莞市路桥所_成都网站设计最加科技_免费软文推广平台_火狐搜索引擎

时间:2025/7/18 9:26:09来源:https://blog.csdn.net/luocong321/article/details/146063301 浏览次数:0次
东莞市路桥所_成都网站设计最加科技_免费软文推广平台_火狐搜索引擎

Spring Boot整合Spring Security与JWT实现无状态认证:实战指南

一、JWT认证原理简介

JSON Web Token(JWT)是一种开放标准(RFC 7519),由三部分组成:

  • Header(头部):声明令牌类型和签名算法
  • Payload(负载):携带用户身份信息
  • Signature(签名):防篡改验证

认证流程:

  1. 客户端提交登录凭证
  2. 服务端验证通过后生成JWT
  3. 客户端后续请求携带JWT
  4. 服务端验证JWT有效性

二、项目搭建与依赖准备

1. 创建Spring Boot项目

选择依赖:

  • Spring Web
  • Spring Security
  • Lombok
  • Spring Data JPA(数据库存储)

2. 添加JWT依赖

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>

三、核心组件实现

1. JWT工具类

public class JwtUtils {private static final String SECRET_KEY = "your-256-bit-secret";private static final long EXPIRATION = 86400000; // 24小时public static String generateToken(UserDetails userDetails) {return Jwts.builder().setSubject(userDetails.getUsername()).claim("roles", userDetails.getAuthorities()).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRATION)).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}public static Claims parseToken(String token) {return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();}public static boolean validateToken(String token, UserDetails userDetails) {final String username = extractUsername(token);return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));}private static boolean isTokenExpired(String token) {return extractExpiration(token).before(new Date());}// 其他辅助方法...
}

2. 自定义UserDetails实现

@Entity
@Data
public class User implements UserDetails {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;@ManyToMany(fetch = FetchType.EAGER)private Set<Role> roles;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());}// 实现其他UserDetails方法...
}

四、安全配置类

1. Spring Security配置

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {private final JwtAuthenticationFilter jwtAuthFilter;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth.requestMatchers("/api/auth/**").permitAll().anyRequest().authenticated()).sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);return http.build();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

2. JWT认证过滤器

@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {private final JwtUtils jwtUtils;private final UserDetailsService userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {final String authHeader = request.getHeader("Authorization");if (authHeader == null || !authHeader.startsWith("Bearer ")) {filterChain.doFilter(request, response);return;}try {final String jwt = authHeader.substring(7);final String username = jwtUtils.extractUsername(jwt);if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (jwtUtils.validateToken(jwt, userDetails)) {UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authToken);}}} catch (Exception e) {logger.error("Cannot set user authentication", e);}filterChain.doFilter(request, response);}
}

五、认证控制器实现

@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {private final AuthenticationManager authenticationManager;private final JwtUtils jwtUtils;private final UserService userService;@PostMapping("/login")public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest request) {Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(),request.getPassword()));SecurityContextHolder.getContext().setAuthentication(authentication);UserDetails userDetails = (UserDetails) authentication.getPrincipal();String jwt = jwtUtils.generateToken(userDetails);return ResponseEntity.ok(new JwtResponse(jwt));}@PostMapping("/register")public ResponseEntity<?> registerUser(@RequestBody RegisterRequest request) {if (userService.existsByUsername(request.getUsername())) {return ResponseEntity.badRequest().body("用户名已存在");}User user = new User();user.setUsername(request.getUsername());user.setPassword(passwordEncoder.encode(request.getPassword()));userService.saveUser(user);return ResponseEntity.ok("用户注册成功");}
}

六、测试验证

使用Postman测试流程:

  1. 注册用户
POST /api/auth/register
{"username": "testuser","password": "Test@1234"
}
  1. 登录获取Token
POST /api/auth/login
{"username": "testuser","password": "Test@1234"
}响应:
{"token": "eyJhbGciOiJIUzI1NiJ9.xxxxxx"
}
  1. 访问受保护接口
GET /api/protected
Headers: Authorization: Bearer <your-token>

七、安全增强措施

  1. 密钥管理:
// 推荐从环境变量读取密钥
private static final String SECRET_KEY = System.getenv("JWT_SECRET");
  1. 刷新令牌机制:
@PostMapping("/refresh-token")
public ResponseEntity<?> refreshToken(HttpServletRequest request) {String refreshToken = jwtUtils.getRefreshTokenFromRequest(request);// 验证刷新令牌并颁发新访问令牌
}
  1. 黑名单机制:
// 登出时将令牌加入黑名单
public void logout(String token) {long expiration = jwtUtils.getExpirationFromToken(token);long currentTime = System.currentTimeMillis();if (expiration > currentTime) {blacklistService.addToBlacklist(token, expiration - currentTime);}
}

八、最佳实践建议

  1. 使用HTTPS传输JWT
  2. 设置合理的令牌有效期(访问令牌1小时,刷新令牌7天)
  3. 存储敏感信息在服务端,Payload只放必要信息
  4. 定期轮换签名密钥
  5. 实现令牌吊销机制
  6. 监控异常认证尝试
  7. 使用强密码策略(至少8位,包含大小写字母、数字和特殊字符)

结语

通过本实践案例,我们实现了基于JWT的无状态认证系统。实际开发中还需要考虑:

  • 分布式系统的会话管理
  • 微服务架构中的令牌传递
  • 第三方登录集成(OAuth2)
  • 审计日志记录

建议结合具体业务需求调整安全策略,并定期进行安全渗透测试。Spring Security与JWT的结合为现代Web应用提供了灵活强大的安全解决方案,正确实施可以有效保护系统资源。

关键字:东莞市路桥所_成都网站设计最加科技_免费软文推广平台_火狐搜索引擎

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: