Quiet
  • 主页
  • 归档
  • 分类
  • 标签
  • 链接
  • 关于我

bajiu

  • 主页
  • 归档
  • 分类
  • 标签
  • 链接
  • 关于我
Quiet主题
  • NodeJs
  • JavaScript

在Express中使用JWT

bajiu
前端

2024-08-10 20:54:00

因为客户端是Electron做得,所以里面集成了Express和SocketIO做前端基础服务,最近服务端要改成前端对登录做JWT,他们只负责做存取,让我们来复习一下JWT基础以及如何在express下实现JWT认证。

JWT 是什么

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境中以紧凑的方式安全地传递信息。它是基于 JSON 格式的,可以在客户端和服务器之间进行传输。

主要特点:

  • 自包含:JWT 可以携带用户信息(如用户 ID、角色等),无需查询数据库,减少请求次数。
  • 安全性:JWT 可以使用签名(如 HMAC SHA256)来防止信息篡改。只有拥有密钥的服务器才能生成有效的 JWT。
  • 跨域认证:JWT 可以用于不同域之间的认证,适合 RESTful API 和单页面应用(SPA)。
  • 可扩展性:可以轻松地在负载中添加自定义声明,以满足不同需求。

结构 - 一个 JWT 通常由三部分组成:

头部(Header):指定令牌的类型(通常是 “JWT”)和所使用的签名算法(如 HMAC SHA256)。

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

有效载荷(Payload):包含声明(claims),如用户信息和其他元数据。可以是预定义的(如 iss、exp、sub 等)或自定义的。

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

签名(Signature):使用头部和有效载荷进行编码,并使用密钥进行签名。这样可以确保令牌的完整性。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

代码

const express = require('express');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const md5 = crypto.createHash('md5');
require('dotenv').config();

const app = express();
app.use(express.json());

const SECRET_KEY = process.env.SECRET_KEY;

app.post('/login', (req, res) => {
    const { username, password } = req.body;

    // 通过MD5问服务端查询接口看密码对不对


    const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: '1h' });
    res.json({ token });
});

function authenticateToken(req, res, next) {
    const token = req.headers['authorization']?.split(' ')[1];
    if (!token) return res.sendStatus(401);

    jwt.verify(token, SECRET_KEY, (err, user) => {
        if (err) return res.sendStatus(403);
        req.user = user;
        next();
    });
}

app.get('/protected', authenticateToken, (req, res) => {
    res.json({ message: '这是一个需要登录的保护的接口', user: req.user });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

然后前端大概这么搞

// 登录
async function login(username, password) {
    const response = await fetch('http://localhost:3000/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ username, password }),
    });

    if (response.ok) {
        const data = await response.json();
        const token = data.token;
        // 将 token 存储在本地存储中(或 Cookie)
        localStorage.setItem('jwt', token);
        console.log('登录成功!', token);
    } else {
        console.error('登录失败');
    }
}

// 使用
async function accessProtectedRoute() {
    const token = localStorage.getItem('jwt'); // 从本地存储中获取 JWT

    const response = await fetch('http://localhost:3000/protected', {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${token}`, // 将 JWT 作为 Bearer token 添加到请求头
        },
    });

    if (response.ok) {
        const data = await response.json();
        console.log('受保护的内容:', data);
    } else {
        console.error('不让用啊');
    }
}
上一篇

NodeJs之child_process

下一篇

electron中使用FFmpeg处理直播流

©2024 By bajiu.