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

相关推荐
咸鱼翻面儿2 分钟前
Javascript异步,这次我真弄懂了!!!
javascript
brrdg_sefg2 分钟前
Rust 在前端基建中的使用
前端·rust·状态模式
o(╥﹏╥)10 分钟前
在 Ubuntu 上安装 VS Code
linux·运维·vscode·ubuntu·vs
m0_7482309427 分钟前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
qq_5895681035 分钟前
Echarts的高级使用,动画,交互api
前端·javascript·echarts
j喬乔36 分钟前
Node导入不了命名函数?记一次Bug的探索
typescript·node.js
不爱学英文的码字机器37 分钟前
[Linux] Shell 命令及运行原理
linux·运维·服务器
cdut_suye1 小时前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
qq_433618441 小时前
shell 编程(三)
linux·运维·服务器
Tlzns1 小时前
Linux网络——UDP的运用
linux·网络·udp