JWT开发详解

文章目录

一、JWT理论基础

JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在网络上以紧凑且自包含的方式安全地传输信息。JWT 被设计为在用户和服务之间传递声明信息,以便进行身份验证和授权。该标准定义了一种简洁的、自包含的方法,可以传递使用 JSON 对象进行编码的信息,这些信息可以被验证和信任。

JWT 由三个部分组成:Header、Payload 和 Signature。这三部分通过.符号分隔,并以Base64编码的形式进行表示。

  1. Header(头部):

    • Header 包含了两部分信息,分别是 token 的类型(JWT)和使用的签名算法,例如:

      json 复制代码
      {
        "alg": "HS256",
        "typ": "JWT"
      }
    • 上述例子表示使用 HMAC SHA-256 算法进行签名。

  2. Payload(负载):

    • Payload 包含了声明(claims)。声明是关于实体(通常是用户)和其他数据的声明。有三种类型的声明:

      • 注册声明(Registered claims): 这些是一组预定义的声明,包括 iss(签发者)、sub(主题)、aud(受众)、exp(过期时间)、nbf(不可用之前的时间)和 iat(发布时间)。
      • 公共声明(Public claims): 可以根据需要定义的声明。
      • 私有声明(Private claims): 用于在同意使用它们的双方之间共享信息。
    • 例如:

      json 复制代码
      {
        "sub": "1234567890",
        "name": "John Doe",
        "admin": true
      }
  3. Signature(签名):

    • 使用编码的 header、编码的 payload 和一个秘密密钥来创建签名部分。签名用于验证消息在传递过程中是否被篡改。

    • 例如:

      复制代码
      HMACSHA256(
        base64UrlEncode(header) + "." +
        base64UrlEncode(payload),
        secret)

JWT 的工作流程通常如下:

  1. 用户进行身份验证,并且身份验证成功后,服务器会生成一个包含用户信息的 JWT,并将其返回给用户。
  2. 用户在之后的请求中将 JWT 放入请求的头部(通常是 Authorization 头部)中。
  3. 服务器在接收到请求时,使用之前共享的密钥来验证 JWT 的签名,以确保信息的完整性。
  4. 如果签名验证成功,服务器可以使用 JWT 中的信息进行授权判断。

优势和特点:

  • 简洁性: JWT 使用 JSON 数据格式,具有良好的可读性和编码/解码的便捷性。
  • 自包含: JWT 包含了所有需要的信息,避免了每次请求时都需要查询数据库的开销。
  • 可靠性: JWT 的签名机制保证了消息的完整性,防止了信息被篡改的可能性。
  • 跨域: 可以在不同的域之间进行信息传递,支持跨域应用场景。

需要注意的是,由于 JWT 使用了 Base64 编码,虽然可以在客户端解码查看,但不能修改,因为修改后签名验证将失败。然而,JWT 中的信息仍然是可见的,因此敏感信息应该被妥善处理。

二、JWT使用实例

2.1 服务端代码

编写一个完整的 JWT 项目涉及多个方面,包括用户认证、生成和验证 JWT、路由保护等。下面是一个简单的示例,使用 Node.js 和 Express 框架实现:

首先,确保你已经安装了 Node.js 和 npm。然后,创建一个新目录,执行以下步骤:

  1. 初始化项目:

    bash 复制代码
    npm init -y
  2. 安装依赖:

    bash 复制代码
    npm install express jsonwebtoken body-parser
  3. 创建一个 server.js 文件:

    javascript 复制代码
    const express = require('express');
    const jwt = require('jsonwebtoken');
    const bodyParser = require('body-parser');
    
    const app = express();
    const PORT = 3000;
    const SECRET_KEY = 'your_secret_key';
    
    app.use(bodyParser.json());
    
    // 用户数据库(示例)
    const users = [
      { id: 1, username: 'user1', password: 'password1' },
      { id: 2, username: 'user2', password: 'password2' },
    ];
    
    // 登录路由
    app.post('/login', (req, res) => {
      const { username, password } = req.body;
    
      // 实际项目中应该通过数据库查询验证用户信息
      const user = users.find((u) => u.username === username && u.password === password);
    
      if (user) {
        // 生成 JWT
        const token = jwt.sign({ userId: user.id, username: user.username }, SECRET_KEY, { expiresIn: '1h' });
        res.json({ token });
      } else {
        res.status(401).json({ error: 'Invalid credentials' });
      }
    });
    
    // 保护路由
    app.get('/protected', (req, res) => {
      const token = req.header('Authorization');
    
      if (!token) {
        return res.status(401).json({ error: 'Unauthorized' });
      }
    
      // 验证 JWT
      jwt.verify(token, SECRET_KEY, (err, decoded) => {
        if (err) {
          return res.status(401).json({ error: 'Invalid token' });
        }
    
        res.json({ message: 'You are authorized!', user: decoded });
      });
    });
    
    app.listen(PORT, () => {
      console.log(`Server is running on http://localhost:${PORT}`);
    });
  4. 运行应用:

    bash 复制代码
    node server.js

现在,你的应用将在 http://localhost:3000 上运行。你可以使用 Postman 或其他工具模拟登录请求,然后将生成的 token 用于访问 /protected 路由。

请注意,以上示例是一个简单的演示,实际项目中需要更复杂的用户认证和安全性措施。在生产环境中,你可能需要使用 HTTPS、存储更安全的密钥、使用数据库进行用户验证等。

2.2 客户端代码

客户端部分通常是一个前端应用,可以使用 HTML、CSS、JavaScript(通常使用框架如 React、Vue.js 或 Angular)来实现。在客户端,主要任务包括用户界面的设计、用户登录、JWT 的处理、以及向服务器发起请求等。

以下是一个简单的 HTML、CSS、JavaScript 示例,使用原生 JavaScript 实现:

  1. 创建一个 index.html 文件:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JWT Demo - Client</title>
</head>
<body>
  <h1>JWT Demo - Client</h1>
  <div id="login-form">
    <label for="username">Username:</label>
    <input type="text" id="username" required>
    <br>
    <label for="password">Password:</label>
    <input type="password" id="password" required>
    <br>
    <button onclick="login()">Login</button>
  </div>
  <div id="protected-content" style="display: none;">
    <h2>Protected Content</h2>
    <p id="message"></p>
  </div>

  <script>
    function login() {
      const username = document.getElementById('username').value;
      const password = document.getElementById('password').value;

      fetch('http://localhost:3000/login', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ username, password }),
      })
      .then(response => response.json())
      .then(data => {
        if (data.token) {
          // 登录成功,显示保护内容
          document.getElementById('login-form').style.display = 'none';
          document.getElementById('protected-content').style.display = 'block';
          document.getElementById('message').innerText = 'Loading...';

          // 使用获取的 token 访问受保护的路由
          fetch('http://localhost:3000/protected', {
            headers: {
              'Authorization': data.token,
            },
          })
          .then(response => response.json())
          .then(protectedData => {
            document.getElementById('message').innerText = `Welcome, ${protectedData.user.username}!`;
          })
          .catch(error => console.error('Error fetching protected content:', error));
        } else {
          alert('Invalid credentials');
        }
      })
      .catch(error => console.error('Login error:', error));
    }
  </script>
</body>
</html>

这个简单的 HTML 文件包含一个登录表单和一个显示受保护内容的部分。当用户成功登录后,它会获取 JWT,并使用该令牌向服务器发起受保护路由的请求。

请注意,这只是一个基础示例,实际项目中应该考虑更多的安全性和用户体验问题。前端应用通常会使用一些框架,以更好地组织和管理代码。

三、JWT流程

以下是一个使用 Mermaid 语法绘制的简单 JWT 流程图:

  1. 提供用户名和密码 2. 验证用户信息 3. 发送JWT 4. 包含JWT的请求 5. 验证JWT 6. 返回受保护资源 用户 服务器 生成JWT 服务器 授权访问

这个流程图简要描述了 JWT 的使用过程:

  1. 用户提供用户名和密码。
  2. 服务器验证用户信息。
  3. 如果验证成功,服务器生成 JWT。
  4. 服务器将包含 JWT 的响应发送给用户。
  5. 用户在后续请求中包含 JWT。
  6. 服务器验证 JWT 并授权用户访问受保护资源。

请注意,这只是一个高层次的概述,实际流程可能因应用场景而异,例如,在生成 JWT 时可能涉及更多的步骤,而在验证 JWT 时可能涉及更多的安全性检查。

相关推荐
John Song几秒前
Linux机器怎么查看进程内存占用情况
linux·运维·chrome
sichuanwuyi3 分钟前
Wydevops工具的价值分析
linux·微服务·架构·kubernetes·jenkins
持戒波罗蜜33 分钟前
ubuntu20解决intel wifi 驱动问题
linux·驱动开发·嵌入式硬件·ubuntu
利刃大大33 分钟前
【Vue】Vue2 和 Vue3 的区别
前端·javascript·vue.js
不做无法实现的梦~43 分钟前
使用ros2来跑通mid360的驱动包
linux·嵌入式硬件·机器人·自动驾驶
Lhuu(重开版1 小时前
JS:正则表达式和作用域
开发语言·javascript·正则表达式
点云SLAM1 小时前
C++内存泄漏检测之Windows 专用工具(CRT Debug、Dr.Memory)和Linux 专业工具(ASan 、heaptrack)
linux·c++·windows·asan·dr.memory·c++内存泄漏检测·c++内存管理
LuiChun1 小时前
Docker Compose 容器服务查询与文件查看操作指南(Windows Docker Desktop 版)【一】
linux·运维·windows·docker·容器
${王小剑}1 小时前
在离线ubuntu上布置深度学习环境
linux·运维·ubuntu
荔枝一杯酸牛奶2 小时前
HTML 表单与表格布局实战:两个经典作业案例详解
前端·html