Java JWT原理及工作流程

 更新时间:2025年05月16日 16:35:49   作者:jkoya  
JWT 是一种简单而强大的身份验证机制,适用于各种前后端分离的项目,通过本文的介绍,你应该对 JWT 的原理、工作流程和使用方法有了更深入的了解,感兴趣的朋友跟随小编一起看看吧

引言

在当代 Web 应用与 API 开发里,用户认证和授权无疑是极为关键的环节。JSON Web Token(JWT)作为一种轻量级的身份验证机制,凭借其简洁性、可扩展性以及跨域支持等显著优势,在众多前后端分离项目中得到了广泛应用。本文将全面深入地探讨 JWT 的原理、工作流程,并且结合 Java 代码示例,展示如何在一个简单的登录系统中运用 JWT 进行认证。

一、JWT 概述

1. 什么是 JWT

JWT 是一种用于在网络应用间安全传递声明的开放标准(RFC 7519)。它通常由三部分构成:头部(Header)、载荷(Payload)和签名(Signature),并以 . 分隔,形成类似 xxxxx.yyyyy.zzzzz 的字符串。

2. JWT 的结构

头部(Header):通常包含两部分信息,令牌的类型(通常是 JWT)和使用的签名算法,如 HMAC SHA256 或 RSA。它是一个 JSON 对象,经过 Base64Url 编码后形成 JWT 的第一部分。

{
  "alg": "HS256",
  "typ": "JWT"
}

载荷(Payload):包含声明(Claims),声明是关于实体(通常是用户)和其他数据的声明。声明分为三种类型:注册声明、公开声明和私有声明。注册声明是一些预定义的声明,如 iss(发行人)、sub(主题)、aud(受众)等。载荷也是一个 JSON 对象,经过 Base64Url 编码后形成 JWT 的第二部分。

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

签名(Signature):为了创建签名部分,需要使用编码后的头部、编码后的载荷、一个密钥(secret)和头部中指定的签名算法。签名用于验证消息在传递过程中没有被更改,并且在使用私钥签名的情况下,还可以验证 JWT 的发送者的身份。

3. JWT 的优点

  • 无状态:JWT 是无状态的,服务器不需要存储会话信息,因此可以很容易地扩展到多个服务器或微服务架构中。
  • 跨域支持:由于 JWT 可以通过 HTTP 头部或 URL 参数传递,因此可以在不同的域之间安全地使用。
  • 可扩展性:可以在载荷中添加自定义声明,以满足不同的业务需求。

二、JWT 工作流程

1. 用户登录

用户向服务器发送登录请求,提供用户名和密码。

2. 服务器验证

服务器验证用户的用户名和密码,如果验证成功,服务器根据用户信息生成一个 JWT。

3. 返回 JWT

服务器将生成的 JWT 返回给客户端。

4. 客户端存储

客户端接收到 JWT 后,将其存储在本地,通常是在浏览器的 localStoragesessionStorage 中。

5. 后续请求

在后续的请求中,客户端将 JWT 包含在请求的头部(通常是 Authorization 头部)中发送给服务器。

6. 服务器验证 JWT

服务器接收到请求后,验证 JWT 的签名和有效期。如果验证成功,服务器认为用户是合法的,并处理请求。

三、代码示例:使用 JWT 实现登录认证

1. 项目环境

我们使用 Java 和 Spring Boot 框架来实现一个简单的登录系统,并使用 io.jsonwebtoken 库来处理 JWT。

2. 引入依赖

pom.xml 中添加以下依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </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>
</dependencies>

3. 代码实现

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class AuthController {
    // 密钥,用于签名和验证 JWT
    private static final String SECRET_KEY = "your_secret_key";
    // 有效期,设置为 30 分钟
    private static final long EXPIRATION_TIME = 30 * 60 * 1000;
    // 模拟用户数据库
    private static final Map<String, String> users = new HashMap<>();
    static {
        users.put("user1", "password1");
        users.put("user2", "password2");
    }
    // 生成 JWT
    private String generateToken(String username) {
        Date now = new Date();
        Date expiration = new Date(now.getTime() + EXPIRATION_TIME);
        return Jwts.builder()
               .setSubject(username)
               .setIssuedAt(now)
               .setExpiration(expiration)
               .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
               .compact();
    }
    // 验证 JWT
    private Claims validateToken(String token) {
        try {
            return Jwts.parser()
                   .setSigningKey(SECRET_KEY)
                   .parseClaimsJws(token)
                   .getBody();
        } catch (Exception e) {
            return null;
        }
    }
    // 登录接口
    @PostMapping("/login")
    public String login(@RequestBody Map<String, String> credentials) {
        String username = credentials.get("username");
        String password = credentials.get("password");
        if (users.containsKey(username) && users.get(username).equals(password)) {
            return generateToken(username);
        }
        return "Invalid credentials";
    }
    // 受保护的接口
    @GetMapping("/protected")
    public String protectedResource(@RequestHeader("Authorization") String token) {
        if (token == null ||!token.startsWith("Bearer ")) {
            return "Token is missing";
        }
        token = token.substring(7);
        Claims claims = validateToken(token);
        if (claims != null) {
            return "Welcome, " + claims.getSubject();
        }
        return "Invalid token";
    }
}

4. 代码解释

  • generateToken 方法:根据用户的用户名生成一个 JWT,包含用户名、签发时间和有效期。
  • validateToken 方法:验证 JWT 的签名和有效期,如果验证成功,返回载荷信息。
  • /login 接口:处理用户的登录请求,验证用户名和密码,如果验证成功,生成并返回 JWT。
  • /protected 接口:受保护的接口,需要在请求头部中包含有效的 JWT 才能访问。

5. 测试

你可以使用 Postman 或者其他工具来测试接口:

  • 登录请求

发送一个 POST 请求到 http://localhost:8080/api/login,请求体为 {"username": "user1", "password": "password1"}

  • 受保护的请求

发送一个 GET 请求到 http://localhost:8080/api/protected,并在请求头中添加 Authorization: Bearer <your_token>

四、JWT 的安全注意事项

  • 密钥安全:密钥是 JWT 签名和验证的关键,必须妥善保管,避免泄露。
  • 有效期设置:合理设置 JWT 的有效期,避免过长的有效期导致安全风险。
  • 防止重放攻击:可以使用一次性令牌或添加时间戳等方式来防止重放攻击。

五、总结

JWT 是一种简单而强大的身份验证机制,适用于各种前后端分离的项目。通过本文的介绍,你应该对 JWT 的原理、工作流程和使用方法有了更深入的了解。在实际开发中,要注意 JWT 的安全问题,确保系统的安全性。希望本文能帮助你在项目中成功应用 JWT 进行登录认证。

到此这篇关于Java JWT详细讲解的文章就介绍到这了,更多相关Java JWT内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot集成Redis实现消息队列的方法

    SpringBoot集成Redis实现消息队列的方法

    这篇文章主要介绍了SpringBoot集成Redis实现消息队列的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • logback打印多次mybatis的sql日志问题

    logback打印多次mybatis的sql日志问题

    这篇文章主要介绍了logback打印多次mybatis的sql日志问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java字符串相关类StringBuffer的用法详解

    Java字符串相关类StringBuffer的用法详解

    java.lang包下的StringBuffer类,代表着可变的字符序列,可以用来对字符串内容进行增删改操作。本文将通过示例详细说说它的用法,感兴趣的可以跟随小编一起学习一下
    2022-10-10
  • Java开发第一个RESTful接口完全攻略

    Java开发第一个RESTful接口完全攻略

    restful接口是一种基于http协议的网络应用程序接口设计风格,它强调资源的表现形式和状态转移,下面这篇文章主要介绍了Java开发RESTful接口的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2026-01-01
  • SpringBoot基于knife4j生成接口文档方式

    SpringBoot基于knife4j生成接口文档方式

    Knife4j介绍一个基于Swagger的JavaAPI文档生成工具,提供美观界面和高级功能,本文详细介绍了在SpringBoot项目中集成Knife4j的方法,包括导入依赖、创建Swagger配置和WebMvcConfiguration配置类等
    2026-05-05
  • Spring的IOC原理详情

    Spring的IOC原理详情

    这篇文章主要介绍了Spring的IOC原理详情,IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为控制反向或者控制倒置
    2022-07-07
  • Java数组从定义到操作全解析

    Java数组从定义到操作全解析

    这篇文章详细介绍了Java数组的概念、声明、创建、访问、初始化、边界、基础操作以及Arrays类的常用方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-11-11
  • 关于idea2022.2 闪退的问题

    关于idea2022.2 闪退的问题

    最近更新了idea2022.2版本,这是一个比较大的软件版本更迭,下面小编给大家介绍下idea2022.2 闪退的问题及解决方法,需要的朋友可以参考下
    2022-08-08
  • Spring注解@Qualifier的详细用法你知道几种

    Spring注解@Qualifier的详细用法你知道几种

    本文给大家分享Spring注解@Qualifier的详细用法,包括@Autowired和@Resource区别介绍,本文通过示例代码给大家详细介绍,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • java获取微信accessToken的方法

    java获取微信accessToken的方法

    这篇文章主要为大家详细介绍了java获取微信accessToken的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09

最新评论