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 时可能涉及更多的安全性检查。

相关推荐
GeW4 分钟前
红帽RHCE从挂科边缘到一次过,我做对了什么
linux
时空自由民.4 分钟前
WSL解决USB 串口连接问题与linux串口权限问题
linux·单片机
OpenPomeloxCommunity13 分钟前
Linux驱动基础(三):firmware的声明与加载
linux·操作系统
高级程序源28 分钟前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
云计算练习生39 分钟前
什么是系统调用?为什么程序访问硬件必须经过它
linux·windows·操作系统·系统调用·操作系统原理
八荒启·交互动画39 分钟前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启
动恰客流统计41 分钟前
线下零售数字化浪潮下,客流统计的3个核心发展趋势
大数据·前端·人工智能
lizz22761 小时前
Babel插件手册
javascript
用户938515635071 小时前
从小米前端面试题,彻底搞懂闭包、作用域链与 useState 惰性初始化
前端·面试
玄芯散人1 小时前
【筑基·059】Linux命令行入门:工程师的操作系统
linux·操作系统·命令行