首页 5G技术

SpringBoot整合JWT:构建安全可靠的RESTful API认证体系

分类:5G技术
字数: (1266)
阅读: (0895)
内容摘要:SpringBoot整合JWT:构建安全可靠的RESTful API认证体系,

在构建现代化的RESTful API时,安全性至关重要。SpringBoot 12 配合 JSON Web Token (JWT) 是一种常用的身份验证和授权机制,可以有效保护你的API接口免受未经授权的访问。本文将深入探讨如何在SpringBoot项目中集成JWT,并分享一些实战中的避坑经验。

JWT 原理与优势

JSON Web Token (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且自包含的方式,用于安全地传输JSON对象作为通信双方之间的令牌。JWT通常用于身份验证和授权,因为它可以包含用户的身份信息和权限声明,并且可以使用数字签名进行验证,确保令牌的完整性和真实性。相比于传统的Session认证方式,JWT具有无状态、可扩展性强等优点,尤其适合于分布式系统和微服务架构。

  • 无状态: 服务器无需存储会话信息,减轻了服务器的负担,更容易扩展。
  • 可扩展性强: JWT包含所有必要信息,可以独立验证,易于在分布式系统中使用。
  • 跨域支持: JWT天然支持跨域认证,可以方便地构建跨域应用程序。

SpringBoot 集成 JWT 的步骤

  1. 添加 JWT 依赖:

    SpringBoot整合JWT:构建安全可靠的RESTful API认证体系

    pom.xml文件中添加jjwt依赖。这里需要注意版本兼容性,避免出现依赖冲突。另外,如果你在使用Spring Security,还需要添加Spring Security相关的依赖。

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version> <!-- 选择与SpringBoot版本兼容的版本 -->
    </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>
    
  2. 定义 JWT 工具类:

    SpringBoot整合JWT:构建安全可靠的RESTful API认证体系

    创建一个JWT工具类,用于生成、验证和解析JWT。这个类通常包含以下方法:

    • generateToken(UserDetails userDetails): 生成JWT。
    • validateToken(String token, UserDetails userDetails): 验证JWT的有效性。
    • getUsernameFromToken(String token): 从JWT中获取用户名。
    @Component
    public class JwtUtil {
    
        @Value("${jwt.secret}") // 从application.properties中读取密钥
        private String secret;
    
        @Value("${jwt.expiration}") // 从application.properties中读取过期时间
        private long expiration;
    
        public String generateToken(UserDetails userDetails) {
            Map<String, Object> claims = new HashMap<>();
            return Jwts.builder()
                    .setClaims(claims)
                    .setSubject(userDetails.getUsername())
                    .setIssuedAt(new Date())
                    .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                    .signWith(SignatureAlgorithm.HS512, secret)
                    .compact();
        }
    
        // 其他方法省略...
    }
    
  3. 配置 Spring Security:

    SpringBoot整合JWT:构建安全可靠的RESTful API认证体系

    如果你使用了Spring Security,需要配置一个JWT过滤器,用于拦截请求并验证JWT。该过滤器需要在UsernamePasswordAuthenticationFilter之前执行。如果你没有使用Spring Security,则需要手动实现请求拦截和JWT验证逻辑。

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private JwtRequestFilter jwtRequestFilter;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                    .antMatchers("/authenticate").permitAll() // 允许/authenticate接口匿名访问
                    .anyRequest().authenticated()
                    .and().sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 设置为无状态Session
    
            http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // 添加JWT过滤器
        }
    }
    
  4. 创建 JWT 过滤器:

    SpringBoot整合JWT:构建安全可靠的RESTful API认证体系

    创建一个JWT过滤器,用于从请求头中获取JWT,验证JWT的有效性,并将用户信息放入Spring Security的上下文中。

    @Component
    public class JwtRequestFilter extends OncePerRequestFilter {
    
        @Autowired
        private JwtUtil jwtUtil;
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
            final String authorizationHeader = request.getHeader("Authorization");
    
            String username = null;
            String jwt = null;
    
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                jwt = authorizationHeader.substring(7);
                username = jwtUtil.getUsernameFromToken(jwt);
            }
    
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
    
                if (jwtUtil.validateToken(jwt, userDetails)) {
    
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    usernamePasswordAuthenticationToken
                            .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                }
            }
            chain.doFilter(request, response);
        }
    }
    
  5. 创建用户认证接口:

    创建一个/authenticate接口,用于接收用户名和密码,验证用户信息,并生成JWT。这里可以对接数据库或者其他的用户数据源进行身份验证。

    @RestController
    public class AuthenticationController {
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private JwtUtil jwtUtil;
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        @PostMapping("/authenticate")
        public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {
            try {
                authenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
                );
            } catch (DisabledException e) {
                throw new Exception("USER_DISABLED", e);
            } catch (BadCredentialsException e) {
                throw new Exception("INVALID_CREDENTIALS", e);
            }
    
            final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
    
            final String jwt = jwtUtil.generateToken(userDetails);
    
            return ResponseEntity.ok(new AuthenticationResponse(jwt));
        }
    }
    

实战避坑经验

  • 密钥安全: 密钥(secret)的安全性至关重要。务必使用高强度的随机字符串作为密钥,并妥善保管,避免泄露。 可以考虑使用环境变量或者外部化配置来管理密钥。
  • 过期时间设置: 合理设置JWT的过期时间,避免令牌被长期滥用。 过期时间过短会导致用户频繁重新登录,影响用户体验;过期时间过长会增加安全风险。
  • 刷新Token: 当JWT过期时,可以使用刷新Token机制来获取新的JWT,而无需用户重新登录。 刷新Token需要单独存储,并需要额外的安全保护。
  • 防止JWT注入攻击: 对JWT进行签名验证,确保JWT没有被篡改。 在服务器端验证JWT的有效性,不要完全信任客户端传递的JWT。
  • 考虑使用HTTPS: 使用HTTPS协议来传输JWT,防止JWT在传输过程中被窃取。
  • Nginx反向代理与负载均衡: 在高并发场景下,可以使用Nginx作为反向代理服务器,将请求分发到多个SpringBoot应用实例上,实现负载均衡。 通过配置Nginx,可以提高系统的吞吐量和可用性。 同时,Nginx也可以作为统一的入口,对请求进行统一的安全验证和权限控制,例如通过Nginx的auth_request模块来验证JWT。

总结

SpringBoot 12 结合 JWT 提供了一种简单而强大的身份验证和授权机制。通过本文的介绍,你应该能够掌握如何在SpringBoot项目中集成JWT,并了解一些实战中的避坑经验。在实际项目中,还需要根据具体的业务需求和安全要求,对JWT进行定制化的配置和扩展,以构建更加安全可靠的RESTful API认证体系。

SpringBoot整合JWT:构建安全可靠的RESTful API认证体系

转载请注明出处: 代码一只喵

本文的链接地址: http://m.acea2.store/blog/018702.SHTML

本文最后 发布于2026-04-15 22:56:45,已经过了11天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 香菜必须死 3 天前
    能不能再详细讲讲刷新Token的实现?感觉这块有点复杂。
  • 摸鱼达人 4 天前
    写得真不错,SpringBoot整合JWT的步骤很清晰,实战避坑经验也很实用!
  • 老实人 6 天前
    感谢分享!正好在研究JWT,这篇文章帮了大忙,少走了很多弯路。
  • 豆腐脑 5 天前
    Nginx那部分也很有用,在高并发场景下,用Nginx做反向代理和负载均衡能有效提高性能。
  • 沙县小吃 6 天前
    感谢分享!正好在研究JWT,这篇文章帮了大忙,少走了很多弯路。