Java中JWT(JSON Web Token)的运用
目录
- 1. JWT的结构
- 2. JWT的优点
- 3. JWT的流转过程
- 4.具体案例
- 一、项目结构
- 二、依赖配置
- 三、用户模型
- 四、JWT工具类
- 五、JWT请求过滤器
- 六、安全配置
- 七、身份验证控制器
- 八、测试JWT
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间以紧凑的方式安全地传递信息。JWT可以被用作身份验证和信息交换的手段,特别适合用于前后端分离的应用程序。
1. JWT的结构
JWT由三部分组成:
-
Header(头部): 通常包含令牌的类型(JWT)和所使用的签名算法(如HMAC SHA256或RSA)。
-
Payload(负载): 包含声明(claims),即要传递的数据。其中可以包含注册声明(如 iss、exp、sub 等)和自定义声明。
-
Signature(签名): 用于验证消息的完整性和发送者的身份。通过将编码后的header和payload与一个密钥结合,利用指定的算法生成。
JWT的格式如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
2. JWT的优点
- 无状态: 不需要在服务器存储会话信息,减轻了服务器的负担。
- 跨域: 可以在不同的域之间进行身份验证。
- 自包含: 含有用户身份信息,避免频繁查询数据库。
3. JWT的流转过程
- 用户通过登录接口发送用户名和密码。
- 服务器验证用户信息,如果成功,则生成JWT并返回给用户。
- 用户在后续请求中带上JWT,通常放在HTTP请求的Authorization头中。
- 服务器解析JWT,验证其有效性,允许或拒绝请求。
4.具体案例
好的,让我们更详细地探讨如何在Java Spring Boot应用程序中实现JWT身份验证,包括每一步的代码和说明。
一、项目结构
Spring Boot项目结构如下:
src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── jwt
│ │ ├── JwtApplication.java
│ │ ├── config
│ │ │ └── SecurityConfig.java
│ │ ├── controller
│ │ │ └── AuthController.java
│ │ ├── model
│ │ │ └── User.java
│ │ ├── service
│ │ │ └── JwtUtil.java
│ │ └── filter
│ │ └── JwtRequestFilter.java
│ └── resources
│ └── application.properties
└── test
二、依赖配置
在pom.xml中添加必要的依赖:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><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>
</dependencies>
三、用户模型
创建一个简单的用户模型:
package com.example.jwt.model;public class User {private String username;private String password;// Constructors, getters, and setters//也可以使用Lombokpublic User(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return username;}public String getPassword() {return password;}
}
四、JWT工具类
创建JWT工具类,负责生成和解析JWT:
package com.example.jwt.service;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
*Jwt工具类
*/
@Component//加入Spring容器
public class JwtUtil {private String secret = "your_secret_key"; // 强密码private long expiration = 60 * 60 * 1000; // 1小时//这个方法用于生成 JWT。它接受用户名作为参数。public String generateToken(String username) {Map<String, Object> claims = new HashMap<>();return createToken(claims, username);}//私有方法,用于实际生成 JWTprivate String createToken(Map<String, Object> claims, String subject) {return Jwts.builder()//开始构建 JWT 的构建器.setClaims(claims)//设置 JWT 中的声明.setSubject(subject)//设置主题(通常是用户名).setIssuedAt(new Date(System.currentTimeMillis()))//设置 JWT 的签发时间.setExpiration(new Date(System.currentTimeMillis() + expiration))//设置 JWT 的过期时间.signWith(SignatureAlgorithm.HS256, secret)//使用指定的算法(HS256)和密钥对 JWT 进行签名.compact();//生成最终的 JWT 字符串}//用于验证给定的 JWT 是否有效。public Boolean validateToken(String token, String username) {final String extractedUsername = extractUsername(token);//提取 JWT 中的用户名return (extractedUsername.equals(username) && !isTokenExpired(token));//检查提取的用户名与提供的用户名是否匹配,并且检查 JWT 是否未过期}//从 JWT 中提取用户名public String extractUsername(String token) {return extractAllClaims(token).getSubject();}//解析 JWT 并返回所有声明private Claims extractAllClaims(String token) {return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}//使用密钥解析 JWT 获取其主体部分(声明)//检查 JWT 是否已过期private Boolean isTokenExpired(String token) {return extractAllClaims(token).getExpiration().before(new Date());}
}
五、JWT请求过滤器
创建JWT请求过滤器,用于拦截请求并验证JWT:
package com.example.jwt.filter;import com.example.jwt.service.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
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;@Component // 将该类标记为 Spring 组件,以便自动扫描和管理
public class JwtRequestFilter extends OncePerRequestFilter {@Autowired // 自动注入 JwtUtil 实例private JwtUtil jwtUtil;@Autowired // 自动注入 UserDetailsService 实例private UserDetailsService userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {// 从请求中获取 Authorization 头部final String authorizationHeader = request.getHeader("Authorization");String username = null; // 初始化用户名String jwt = null; // 初始化 JWT 令牌// 检查 Authorization 头部是否存在且以 "Bearer " 开头if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {// 提取 JWT 令牌(去掉 "Bearer " 前缀)jwt = authorizationHeader.substring(7);// 从 JWT 中提取用户名username = jwtUtil.extractUsername(jwt);}// 如果用户名不为空且当前 SecurityContext 没有身份验证信息if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {// 根据用户名加载用户详细信息UserDetails userDetails = userDetailsService.loadUserByUsername(username);// 验证 JWT 是否有效if (jwtUtil.validateToken(jwt, userDetails.getUsername())) {// 创建身份验证令牌,并设置用户的权限UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());// 设置请求的详细信息authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));// 将身份验证信息存入 SecurityContextSecurityContextHolder.getContext().setAuthentication(authenticationToken);}}// 继续过滤器链chain.doFilter(request, response);}
}
六、安全配置
配置Spring Security,以保护API并使用JWT:
package com.example.jwt.config;import com.example.jwt.filter.JwtRequestFilter;
import org.springframework.beans.factory.annotation.Autowired;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtRequestFilter jwtRequestFilter;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/auth/login").permitAll() // 公开登录接口.anyRequest().authenticated() // 其他接口需要认证.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 无状态会话// 添加JWT过滤器http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("password")).roles("USER"); // 示例用户}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}
七、身份验证控制器
创建一个控制器来处理登录请求并返回JWT:
package com.example.jwt.controller;import com.example.jwt.model.User;
import com.example.jwt.service.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/auth")
public class AuthController {@Autowiredprivate JwtUtil jwtUtil;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate UserDetailsService userDetailsService;@PostMapping("/login")public String login(@RequestBody User user) {try {authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));} catch (Exception e) {throw new RuntimeException("Invalid credentials");}final UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());return jwtUtil.generateToken(userDetails.getUsername());}
}
八、测试JWT
- 启动Spring Boot应用程序。
- 使用Postman或其他工具测试登录接口。
请求示例:
POST /auth/login
Content-Type: application/json{"username": "user","password": "password"
}
响应示例:
{"token": "eyJhbGciOiJIUzI1NiIsInR5c..."
}
- 使用返回的token访问受保护的资源:
GET /protected/resource
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5c...
相关文章:
Java中JWT(JSON Web Token)的运用
目录 1. JWT的结构2. JWT的优点3. JWT的流转过程4.具体案例一、项目结构二、依赖配置三、用户模型四、JWT工具类五、JWT请求过滤器六、安全配置七、身份验证控制器八、测试JWT JWT(JSON Web Token)是一种开放标准(RFC 7519)&#…...
CSS3练习--电商web
免责声明:本文仅做分享! 目录 小练--小兔鲜儿 目录构建 SEO 三大标签 Favicon 图标 布局网页 版心 快捷导航(shortcut) 头部(header) logo 导航 搜索 购物车 底部(footer࿰…...
Linux 默认内核版本更改
随笔记录 目录 1. 背景介绍 2. 解决方法 2.1 查看所有可用版本 2.2 安装指定版本内核 2.3 检查当前内核列表 2.4 检查当前默认内核 2.5 设置新的默认内核 2.6 确认内核是否成功加载 2.7 重启 2.8 删除其他版本内核 1. 背景介绍 linux 一般安装多个内核版本&…...
【ubuntu】修改用户名、主机名、主文件夹名、登录名、密码
目录 1.他们是什么 2.修改方法 2.1 修改用户密码 2.2 修改主机名 2.2.1 切换到root用户 2.2.2 修改名称 2.3 修改用户名 主文件夹名 登录名 2.2.1 sudoers 2.2.2 passwd 2.2.3 shadow 2.2.4 group 2.2.5 修改主文件夹名 3.重启 1.他们是什么 (1…...
深入理解JavaScript 的原型继承
JavaScript 的原型链继承机制和 Java 的类继承机制有明显的区别,虽然它们都用于实现对象之间的继承,但它们的实现方式、概念以及运行机制都不同。 1. JavaScript 的原型继承 JavaScript 是基于原型链的继承,主要依赖对象的 __proto__ 属性或…...
Error while loading conda entry point: conda-libmamba-solver
问题 解决方法 conda install --solverclassic conda-forge::conda-libmamba-solver conda-forge::libmamba conda-forge::libmambapy conda-forge::libarchive...
FANUC机器人—PCDK
前言 FANUC提供了一种使用其 PC 开发人员套件 (PCDK) 从 PC 命令和配置机器人的简单方法。该套件允许 PC 访问机器人上的变量、寄存器、IO、程序、位置和警报;接下来,我将如何开始使用 C#。 连接到机器人 将以下突出显示的行添加…...
如何在wsl中使用beyond compare
寫一個名為bc4的文件,內容如下: #!/bin/sh /mnt/c/Program\ Files/Beyond\ Compare\ 4/BComp.com $(wslpath -aw $1) $(wslpath -aw $2)bc4 file1 file2參考:https://forum.scootersoftware.com/forum/beyond-compare-4-discussion/version-…...
CNN+Transformer在自然语言处理中的具体应用
在自然语言处理(NLP)领域,CNN(卷积神经网络)和Transformer架构各自有着广泛的应用。NLP中的具体应用: CNN在NLP中的应用 1.文本分类:CNN可以用于文本分类任务,如情感分析、垃圾邮件…...
DotNetty ChannelRead接收数据为null
问题:C#使用Dotnetty和Java netty服务器通讯,结果能正确发送数据到服务器,却始终接收不到服务器返回的数据。 解决:一定一定要注意服务器和客户端使用的编码一定要完全一样才行 我先前在客户端添加了StringDecoder,服务器却没有…...
3分钟学会下载 blender
1. blender简介 Blender是一款开源的3D创作套件,它由Blender Foundation维护,并得到了全球志愿者和专业开发者的支持。Blender广泛应用于3D模型的制作、动画、渲染、视频编辑、游戏创建、模拟、 composting以及3D打印等多个领域。 功能特点:…...
实现Xshell与虚拟机中Linux服务器的连接(附常见错误解决)
前言 Xshell是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 本文将介绍Xshell与虚拟机中Linux服务器连接…...
Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)
文章目录 esp-rs 简介GithubRust 包仓库Rust 教程Wokwi 电子模拟器开发环境Rust 环境esp-rs 环境创建 ESP32C3 项目项目结构编译项目命令运行模拟器ESP32C3 烧录 esp-rs 简介 esp-rs 是一个专注于为 Espressif 系列芯片(如 ESP32、ESP32-S2、ESP32-C3 等࿰…...
项目-坦克大战笔记-墙体销毁以及人机销毁
在子弹撞到墙或者人机身上时会将碰撞到的墙体或者人机销毁 我们需要做到几点 检测子弹碰撞到的墙体或者人机将物体获取到 每帧遍历墙体列表与人机列表,检测被碰撞的墙,创建一个方法返回值为对应类型将被碰撞的物体返回出来 public static gudin wallp…...
硬件设计-利用环路设计优化PLL的输出性能
目录 前言 问题描述 问题分析步骤 杂散源头排查 245.76M 参考相噪: 30.72M VCXO的相噪性能测试如下: 解决方案 前言 LMK04832是TI 新发布的低抖动双环去抖模拟时钟, 其最高输出频率可以到达3250MHz, 输出抖动极低,3200MHz…...
Vue入门-Node.js安装
进入Node.js中文网 点击进入Node.js中文网 或者手动输入网址: https://www.nodejs.com.cn/download.html 点击下载64位安装包: 下载好之后双击进行安装 可选择个性化安装或默认安装 直接点【Next】按钮,此处可根据个人需求…...
OpenCV threhold()函数
OpenCV threhold()函数的主要用途是将灰度图转换为二值图像,实现灰度图的二值化,在机器视觉中使用频度较高,如尺寸量测,物体识别等。其原型如下: 函数参数: src 输入数组(多通道、8 位或 32 位浮点…...
Qt教程(002):Qt项目创建于框架介绍
二、创建Qt项目 2.1 创建项目 【1、New Project】 【2、选择Qt Widgets Application】 【3、设置项目名称和保存路径】 注意,项目名称和路径不要带中文。 【4、选择QWidget】 带菜单栏的窗口QMainWindow空白窗口QWidget对话框窗口QDialog 【5、编译】 2.2 项目框…...
《C++游戏人工智能开发:开启智能游戏新纪元》
在当今的游戏世界中,人工智能(AI)已经成为了不可或缺的一部分。它能够为游戏增添深度、挑战性和真实感,让玩家沉浸其中,享受前所未有的游戏体验。而对于 C开发者来说,如何在 C中实现高效的游戏人工智能开发…...
SPSS and Origin Paired Samples T-Test
SPSS https://www.spss-tutorials.com/spss-paired-samples-t-test/ Testing the Normality Assumption We can now test the normality assumption by running a Shapiro-Wilk test ora Kolmogorov-Smirnov test. Origin分析 两个软件计算的一样...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
