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

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.mzph.cn/bicheng/68240.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

说一说mongodb组合索引的匹配规则

一、背景 有一张1000多万条记录的大表&#xff0c;需要做归档至历史表&#xff0c;出现了大量慢查询。 查询条件是 "classroomId": {$in: ["xxx", "xxx", ..... "xxx","xxx", "xxx" ] }耗时近5秒&#xff0c;且…

更新java

下载 Java 下载 |神谕 (oracle.com)

CSS3的aria-hidden学习

前言 aria-hidden 属性可用于隐藏非交互内容&#xff0c;使其在无障碍 API 中不可见。即当aria-hidden"true" 添加到一个元素会将该元素及其所有子元素从无障碍树中移除&#xff0c;这可以通过隐藏来改善辅助技术用户的体验&#xff1a; 纯装饰性内容&#xff0c;如…

【Java设计模式-5】装饰模式:给咖啡加点“佐料”

今天咱们要探索一下Java世界里的装饰模式&#xff08;Decorator Pattern&#xff09;。为了让这个过程更加生动易懂&#xff0c;咱们就以大家都熟悉的咖啡饮品来举例吧&#xff0c;想象一下&#xff0c;你就是那个咖啡大师&#xff0c;要给顾客调制出各种独特口味的咖啡哦&…

C++(5)

1.运算符重载 头文件 #ifndef MYSTRING_H #define MYSTRING_H#include <iostream> #include <cstring>using namespace std;class myString { private:char *str;//C风格字符串int size0; public:std::string s_str;//转换构造函数myString(const std::string &a…

K8S--配置存活、就绪和启动探针

目录 1 本人基础环境2 目的3 存活、就绪和启动探针介绍3.1 存活探针3.2 就绪探针3.3 启动探针 4 探针使用场景4.1 存活探针4.2 就绪探针4.3 启动探针 5 配置存活、就绪和启动探针5.1 定义存活探针5.2 定义一个存活态 HTTP 请求接口5.3 定义 TCP 的就绪探针、存活探测5.4 定义 g…

【HTML+CSS+JS+VUE】web前端教程-36-JavaScript简介

JavaScript介绍 JavaScript是一种轻量级的脚本语言&#xff0c;所谓脚本语言&#xff0c;指的是它不具备开发操作系统的能力&#xff0c;而是用来编写控制其他大型应用程序的“脚本” JavaScript是一种嵌入式语言&#xff0c;它本身提供的核心语法不算很多 为什么学习JavaScri…

LLM实现视频切片合成 前沿知识调研

1.相关产品 产品链接腾讯智影https://zenvideo.qq.com/可灵https://klingai.kuaishou.com/即梦https://jimeng.jianying.com/ai-tool/home/Runwayhttps://aitools.dedao.cn/ai/runwayml-com/Descripthttps://www.descript.com/?utm_sourceai-bot.cn/Opus Cliphttps://www.opu…

AI多模态论文解读:LLaVA-CoT:让视觉语言模型逐步推理

本文作者&#xff1a;AIGCmagic社区 猫先生 一、简 介 LLaVA-CoT引入了四个不同的阶段&#xff08;摘要、标题、推理和结论&#xff09;&#xff0c;使模型能够独立进行系统化的多阶段推理&#xff0c;显著提高了在推理密集型任务上的准确性。 编译了LLaVA-CoT-100k数据集&am…

分布式缓存redis

分布式缓存redis 1 redis单机&#xff08;单节点&#xff09;部署缺点 &#xff08;1&#xff09;数据丢失问题&#xff1a;redis是内存存储&#xff0c;服务重启可能会丢失数据 &#xff08;2&#xff09;并发能力问题&#xff1a;redis单节点&#xff08;单机&#xff09;部…

《C++11》nullptr介绍:从NULL说起

在C11之前&#xff0c;我们通常使用NULL来表示空指针。然而&#xff0c;NULL在C中有一些问题和限制&#xff0c;这就是C11引入nullptr的原因。本文将详细介绍nullptr的定义、用法和优点。 1. NULL的问题 在C中&#xff0c;NULL实际上是一个整数0&#xff0c;而不是一个真正的…

供应链数字化转型参考大型供应链系统技术架构设计方案

该文介绍了一个大型供应链系统技术架构的设计方案&#xff0c;包括整体设计、核心技术目录和应用案例。设计采用Choerodon微服务框架&#xff0c;关注海量并发、可伸缩性、安全性等方面。同时&#xff0c;方案符合大型企业结构的HR组织架构&#xff0c;支持多级组织架构和角色、…

STM32F1学习——DMA直接存储器存取

一、DMA直接存储器存取 DMA的全称是 Direct Memory Access 直接存储器存取&#xff0c;他可以提供外设和存储器间或存储器和存储器间的高速数据传输&#xff0c;无需CPU的干预。 STM32有12个DMA通道&#xff0c;由DMA1(7个通道组成)和DMA2(5个通道组成)&#xff0c;STM32F103C8…

一个使用 Golang 编写的新一代网络爬虫框架,支持JS动态内容爬取

大家好&#xff0c;今天给大家分享一个由ProjectDiscovery组织开发的开源“下一代爬虫框架”Katana&#xff0c;旨在提供高效、灵活且功能丰富的网络爬取体验&#xff0c;适用于各种自动化管道和数据收集任务。 项目介绍 Katana 是 ProjectDiscovery 精心打造的命令行界面&…

6.2 MySQL时间和日期函数

以前我们就用过now()函数来获得系统时间&#xff0c;用datediff()函数来计算日期相差的天数。我们在计算工龄的时候&#xff0c;让两个日期相减。那么其中的这个now函数返回的就是当前的系统日期和时间。 1. 获取系统时间函数 now()函数&#xff0c;返回的这个日期和时间的格…

用 Python 处理 CSV 和 Excel 文件

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

vulnhub靶场【IA系列】之Tornado

前言 靶机&#xff1a;IA-Tornado&#xff0c;IP地址为192.168.10.11 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.2 都采用虚拟机&#xff0c;网卡为桥接模式 本文所用靶场、kali镜像以及相关工具&#xff0c;我放置在网盘中&#xff0c;可以复制后面链接查看 htt…

[云讷科技] 用于软件验证的仿真环境

我们使用Pursuit自动驾驶仪为各种场景设计仿真环境&#xff0c;以便用户可以在模拟环境中直接验证他们的软件&#xff0c;无需现场测试。该环境基于Gazebo引擎。 1. 工作区目录 模拟环境的工作区位于提供的U盘中的~/pursuit_space/sitl_space_pursuit中。用户可以按照用户手册…

【Uniapp-Vue3】页面生命周期onLoad和onReady

一、onLoad函数 onLoad在页面载入时触发&#xff0c;多用于页面跳转时进行参数传递。 我们在跳转的时候传递参数name和age: 接受参数&#xff1a; import {onLoad} from "dcloudio/uni-app"; onLoad((e)>{...}) 二、onReady函数 页面生命周期函数中的onReady其…

iOS 解决两个tableView.嵌套滚动手势冲突

我们有这样一个场景&#xff0c;就是页面上有一个大的tableView&#xff0c; 每一个cell都是和屏幕一样高的&#xff0c;然后cell中还有一个可以 tableView&#xff0c;比如直播间的情形&#xff0c;这个时候如果我们拖动 cell里面的tableView滚动的话&#xff0c;如果滚动到内…