当前位置: 首页 > news >正文

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的流转过程

  1. 用户通过登录接口发送用户名和密码。
  2. 服务器验证用户信息,如果成功,则生成JWT并返回给用户。
  3. 用户在后续请求中带上JWT,通常放在HTTP请求的Authorization头中。
  4. 服务器解析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

  1. 启动Spring Boot应用程序。
  2. 使用Postman或其他工具测试登录接口。

请求示例:

POST /auth/login
Content-Type: application/json{"username": "user","password": "password"
}

响应示例:

{"token": "eyJhbGciOiJIUzI1NiIsInR5c..."
}
  1. 使用返回的token访问受保护的资源:
GET /protected/resource
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5c...

相关文章:

Java中JWT(JSON Web Token)的运用

目录 1. JWT的结构2. JWT的优点3. JWT的流转过程4.具体案例一、项目结构二、依赖配置三、用户模型四、JWT工具类五、JWT请求过滤器六、安全配置七、身份验证控制器八、测试JWT JWT&#xff08;JSON Web Token&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#…...

CSS3练习--电商web

免责声明&#xff1a;本文仅做分享&#xff01; 目录 小练--小兔鲜儿 目录构建 SEO 三大标签 Favicon 图标 布局网页 版心 快捷导航&#xff08;shortcut&#xff09; 头部&#xff08;header&#xff09; logo 导航 搜索 购物车 底部&#xff08;footer&#xff0…...

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.他们是什么 &#xff08;1&#xf…...

深入理解JavaScript 的原型继承

JavaScript 的原型链继承机制和 Java 的类继承机制有明显的区别&#xff0c;虽然它们都用于实现对象之间的继承&#xff0c;但它们的实现方式、概念以及运行机制都不同。 1. JavaScript 的原型继承 JavaScript 是基于原型链的继承&#xff0c;主要依赖对象的 __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 开发人员套件 &#xff08;PCDK&#xff09; 从 PC 命令和配置机器人的简单方法。该套件允许 PC 访问机器人上的变量、寄存器、IO、程序、位置和警报&#xff1b;接下来&#xff0c;我将如何开始使用 C#。 连接到机器人 将以下突出显示的行添加…...

如何在wsl中使用beyond compare

寫一個名為bc4的文件&#xff0c;內容如下&#xff1a; #!/bin/sh /mnt/c/Program\ Files/Beyond\ Compare\ 4/BComp.com $(wslpath -aw $1) $(wslpath -aw $2)bc4 file1 file2參考&#xff1a;https://forum.scootersoftware.com/forum/beyond-compare-4-discussion/version-…...

CNN+Transformer在自然语言处理中的具体应用

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;CNN&#xff08;卷积神经网络&#xff09;和Transformer架构各自有着广泛的应用。NLP中的具体应用&#xff1a; CNN在NLP中的应用 1.文本分类&#xff1a;CNN可以用于文本分类任务&#xff0c;如情感分析、垃圾邮件…...

DotNetty ChannelRead接收数据为null

问题&#xff1a;C#使用Dotnetty和Java netty服务器通讯&#xff0c;结果能正确发送数据到服务器&#xff0c;却始终接收不到服务器返回的数据。 解决&#xff1a;一定一定要注意服务器和客户端使用的编码一定要完全一样才行 我先前在客户端添加了StringDecoder,服务器却没有…...

3分钟学会下载 blender

1. blender简介 Blender是一款开源的3D创作套件&#xff0c;它由Blender Foundation维护&#xff0c;并得到了全球志愿者和专业开发者的支持。Blender广泛应用于3D模型的制作、动画、渲染、视频编辑、游戏创建、模拟、 composting以及3D打印等多个领域。 功能特点&#xff1a…...

实现Xshell与虚拟机中Linux服务器的连接(附常见错误解决)

前言 Xshell是一个强大的安全终端模拟软件&#xff0c;它支持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 系列芯片&#xff08;如 ESP32、ESP32-S2、ESP32-C3 等&#xff0…...

项目-坦克大战笔记-墙体销毁以及人机销毁

在子弹撞到墙或者人机身上时会将碰撞到的墙体或者人机销毁 我们需要做到几点 检测子弹碰撞到的墙体或者人机将物体获取到 每帧遍历墙体列表与人机列表&#xff0c;检测被碰撞的墙&#xff0c;创建一个方法返回值为对应类型将被碰撞的物体返回出来 public static gudin wallp…...

硬件设计-利用环路设计优化PLL的输出性能

目录 前言 问题描述 问题分析步骤 杂散源头排查 245.76M 参考相噪&#xff1a; 30.72M VCXO的相噪性能测试如下: 解决方案 前言 LMK04832是TI 新发布的低抖动双环去抖模拟时钟&#xff0c; 其最高输出频率可以到达3250MHz&#xff0c; 输出抖动极低&#xff0c;3200MHz…...

Vue入门-Node.js安装

进入Node.js中文网 ​​​​​​​点击进入Node.js中文网 或者手动输入网址&#xff1a; https://www.nodejs.com.cn/download.html 点击下载64位安装包&#xff1a; 下载好之后双击进行安装 可选择个性化安装或默认安装 直接点【Next】按钮&#xff0c;此处可根据个人需求…...

OpenCV threhold()函数

OpenCV threhold()函数的主要用途是将灰度图转换为二值图像,实现灰度图的二值化&#xff0c;在机器视觉中使用频度较高&#xff0c;如尺寸量测&#xff0c;物体识别等。其原型如下&#xff1a; 函数参数&#xff1a; src 输入数组&#xff08;多通道、8 位或 32 位浮点&#xf…...

Qt教程(002):Qt项目创建于框架介绍

二、创建Qt项目 2.1 创建项目 【1、New Project】 【2、选择Qt Widgets Application】 【3、设置项目名称和保存路径】 注意&#xff0c;项目名称和路径不要带中文。 【4、选择QWidget】 带菜单栏的窗口QMainWindow空白窗口QWidget对话框窗口QDialog 【5、编译】 2.2 项目框…...

《C++游戏人工智能开发:开启智能游戏新纪元》

在当今的游戏世界中&#xff0c;人工智能&#xff08;AI&#xff09;已经成为了不可或缺的一部分。它能够为游戏增添深度、挑战性和真实感&#xff0c;让玩家沉浸其中&#xff0c;享受前所未有的游戏体验。而对于 C开发者来说&#xff0c;如何在 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分析 两个软件计算的一样...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...