java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java JWT

Java JWT原理及工作流程

作者: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 工作流程

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. 代码解释

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 进行登录认证。

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

您可能感兴趣的文章:
阅读全文