JAVA:Spring Boot 集成 JWT 实现身份验证的技术指南

news/2025/1/15 11:46:28/

1、简述

在现代Web开发中,安全性尤为重要。为了确保用户的身份,JSON Web Token(JWT)作为一种轻量级且无状态的身份验证方案,广泛应用于微服务和分布式系统中。本篇博客将讲解如何在Spring Boot 中集成JWT实现身份验证,并列出具体代码示例和常见应用场景。

在这里插入图片描述

2、什么是JWT?

JWT是一种开放标准(RFC 7519),定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象。它包含三个部分:头部(Header)、载荷(Payload)和签名(Signature)。

  • 头部:通常包含令牌类型(JWT)和签名算法(如HMAC SHA256)。
  • 载荷:包含声明(claims),如用户ID和到期时间。
  • 签名:使用头部中的算法对头部和载荷进行签名,确保令牌未被篡改。

为什么使用JWT?

  • 无状态性(Stateless):JWT自包含信息,不需要服务器存储会话数据,适合分布式系统。
  • 跨平台:JWT是基于JSON格式的,因此在不同语言和平台之间传递信息非常方便。
  • 安全性:JWT使用签名验证信息的完整性,确保数据传输的安全性。

在这里插入图片描述

3、集成

3.1 项目设置

首先,创建一个Spring Boot项目,并添加以下依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2 创建JWT工具类

创建一个JwtUtils类,用于生成和验证JWT:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;@Component
public class JwtUtils {private final String secret = "yourSecretKey";private final long expiration = 86400000; // 1 day in millisecondspublic String generateToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + expiration)).signWith(SignatureAlgorithm.HS512, secret).compact();}public String getUsernameFromToken(String token) {Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();return claims.getSubject();}public boolean validateToken(String token) {try {Jwts.parser().setSigningKey(secret).parseClaimsJws(token);return true;} catch (Exception e) {return false;}}
}
3.3 创建身份验证过滤器

创建一个JwtAuthenticationFilter类,用于拦截和验证JWT:

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class JwtAuthenticationFilter extends OncePerRequestFilter {private final JwtUtils jwtUtils;public JwtAuthenticationFilter(JwtUtils jwtUtils) {this.jwtUtils = jwtUtils;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {String jwt = extractJwtFromRequest(request);if (jwt != null && jwtUtils.validateToken(jwt)) {String username = jwtUtils.getUsernameFromToken(jwt);UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, null);authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authentication);}filterChain.doFilter(request, response);}private String extractJwtFromRequest(HttpServletRequest request) {String bearerToken = request.getHeader("Authorization");if (bearerToken != null && bearerToken.startsWith("Bearer ")) {return bearerToken.substring(7);}return null;}
}
3.4 配置Spring Security

配置Spring Security以使用JWT进行身份验证:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {private final JwtUtils jwtUtils;public SecurityConfig(JwtUtils jwtUtils) {this.jwtUtils = jwtUtils;}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/api/auth/**").permitAll().anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);http.addFilterBefore(new JwtAuthenticationFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 配置认证管理器}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}
3.5 实现认证控制器

创建一个认证控制器,用于处理用户登录并生成JWT:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/auth")
public class AuthController {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate JwtUtils jwtUtils;@Autowiredprivate UserDetailsService userDetailsService;@PostMapping("/login")public String authenticateUser(@RequestBody AuthRequest authRequest) throws AuthenticationException {Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword()));UserDetails userDetails = (UserDetails) authentication.getPrincipal();return jwtUtils.generateToken(userDetails.getUsername());}
}class AuthRequest {private String username;private String password;// Getters and setters
}

4、应用场景

  • 用户登录
    当用户登录时,服务器验证其凭据并生成一个JWT。客户端将这个JWT存储在本地(例如,LocalStorage或Cookie中),并在后续请求中通过HTTP头部传递。

  • API访问控制
    在后续的API请求中,服务器通过验证JWT来确保请求者的身份和权限。这可以用于保护敏感数据和功能。

  • 分布式系统
    在微服务架构中,各个服务之间可以使用JWT进行身份验证和信息传递,无需集中存储和管理会话状态。

  • 无状态应用
    对于需要无状态会话的应用,JWT是理想的选择,因为它不需要服务器保存会话数据,减轻了服务器的负担。

5、总结

通过本文的介绍,您应该已经了解了如何在Spring Boot应用中集成JWT,以及它的实际应用场景。JWT提供了一种轻量级且安全的身份验证方式,适合现代分布式系统和无状态应用。希望本文能帮助您在项目中实现JWT身份验证,提升应用的安全性和扩展性。


http://www.ppmy.cn/news/1563310.html

相关文章

day08_Kafka

文章目录 day08_Kafka课程笔记一、今日课程内容一、消息队列&#xff08;了解&#xff09;**为什么消息队列就像是“数据的快递员”&#xff1f;****实际意义**1、产生背景2、消息队列介绍2.1 常见的消息队列产品2.2 应用场景2.3 消息队列中两种消息模型 二、Kafka的基本介绍1、…

Logback日志技术

Logback日志技术 日志 日志&#xff08;Logging&#xff09;是软件开发和运维中用于记录系统或应用程序运行期间发生的运行信息、状态变化、错误信息等的一种机制&#xff0c;这种记录的方式就好像我们日常生活中写日记一样。它提供了一种持久化的方式&#xff0c;使得开发者…

webpack04服务器配置

webpack配置 entryoutput filenamepathpublicPath 。。 打包引入的基本路径&#xff0c;&#xff0c;&#xff0c;比如引入一个bundle.js,。引用之后的路径就是 publicPathfilename -devServer:static : 静态文件的位置。。。hostportopencompress : 静态资源是否用gzip压缩hi…

Flutter 多终端测试 自定义启动画面​​​​​​​ 更换小图标和应用名称

多终端测试 flutter devices flutter run -d emulator-5554 flutter run -d emulator-5556 自定义启动画面 之前&#xff1a; 进入assert 3x 生成 1x 2x dart run flutter_native_splash:create dart run flutter_native_splash:remove 现在&#xff08;flutter_nativ…

vue实现淘宝web端,装饰淘宝店铺APP,以及后端设计成能快速响应前端APP

一、前端实现 实现一个类似于淘宝店铺的装饰应用&#xff08;APP&#xff09;是一个复杂的任务&#xff0c;涉及到前端界面设计、拖放功能、模块化组件、数据管理等多个方面。为了简化这个过程&#xff0c;我们可以创建一个基本的 Vue 3 应用&#xff0c;允许用户通过拖放来添…

电梯系统的UML文档02

现在我们来回答用UML 设计电梯系统的实践中遇到的问题&#xff1a;“UML 是一种适合于实时系统的建模语言吗?”我们发现基于上段提到的特征&#xff0c;UML 是适合的但有不足。用UML 设计实时系统有以下问题&#xff1a; •特定硬件及它们特征的定义。 •在对象、任务和硬件层…

AppBarLayout 与 NestedScrollView 的滚动行为不生效

问题描述与处理策略 1、问题描述 如下布局文件&#xff0c;AppBarLayout 与 NestedScrollView 的滚动行为不生效 <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://sch…

机器学习 - 如何理解几何学中的超平面 ?

线性回归公式 ywTxb 是数据建模中的基础&#xff1a; 数学上&#xff0c;它是一个线性函数。几何上&#xff0c;它是一个超平面。 那么如何理解超平面这个概念呢&#xff1f; 超平面&#xff08;hyperplane&#xff09;是几何学中的一个基本概念&#xff0c;尤其在高维空间和…