Nodejs 使用 JSON Web Token 认证实例

创建
阅读 514

初始化

npm init -y
npm i express dotenv jsonwebtoken

环境变量

ACCESS_TOKEN_SECRET=dbf8de
REFRESH_TOKEN_SECRET=7ac2a3

项目代码

const express = require('express');
const app = express();
require('dotenv').config();
const jwt = require('jsonwebtoken');
app.use(express.json());

const posts = [
  {
    username: 'Kyle',
    title: 'Post 1',
  },
  {
    username: 'Jim',
    title: 'Post 1',
  },
];

// 临时保存 refreshTokens,实际应用可以保存到数据库中
let refreshTokens = [];

// 登录,获取accessToken、 refreshToken
app.post('/login', (req, res) => {
  // Authenticate User
  const username = req.body.username;
  const user = { name: username };
  const accessToken = generateAccessToken(user);
  const refreshToken = jwt.sign(user, process.env.REFRESH_TOKEN_SECRET);
  refreshTokens.push(refreshToken);
  res.json({
    accessToken,
    refreshToken,
  });
});

// 通过 refreshToken 获取 accessToken
app.post('/token', (req, res) => {
  const refreshToken = req.body.token;
  if (refreshToken == null) return res.sendStatus(401);
  if (!refreshTokens.includes(refreshToken)) return res.sendStatus(403);

  jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    const accessToken = generateAccessToken({ name: user.name });
    res.json({ accessToken });
  });
});

// 获取需要认证的文章
app.get('/posts', authenticateToken, (req, res) => {
  res.json(posts.filter((post) => post.username === req.user.name));
});

// 退出登录 删除 refreshToken
app.delete('/logout', (req, res) => {
  refreshTokens = refreshTokens.filter((token) => token !== req.body.token);
  res.sendStatus(204);
});

// 认证中间件
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  if (token == null) {
    return res.sendStatus(401);
  }
  jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
    if (err) {
      return res.sendStatus(403);
    }
    req.user = user;
    next();
  });
}

// 生成token
function generateAccessToken(user) {
  return jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, {
    expiresIn: '30s',
  });
}

app.listen(3000);

请求示例

request.http

###
POST http://localhost:3000/login
Content-Type: application/json

{
  "username":"Jim"
}

###
POST http://localhost:3000/token
Content-Type: application/json

{
  "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmltIiwiaWF0IjoxNTgzNDkxMjUzfQ.aM_n0O2nt5TXBIrolk7mk9wvXvMHrhYzdJ7FdFWCd8U"
}

###
GET http://localhost:3000/posts
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmltIiwiaWF0IjoxNTgzNDkxMjcyLCJleHAiOjE1ODM0OTEzMDJ9.W7mrj8Jr9sMQ1vIVB-uI_lZdHVCixlC3DVb3lmf9zJU

###
GET http://localhost:3000/logout
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmltIiwiaWF0IjoxNTgzNDkxMjcyLCJleHAiOjE1ODM0OTEzMDJ9.W7mrj8Jr9sMQ1vIVB-uI_lZdHVCixlC3DVb3lmf9zJU

更新记录

  1. 2020-03-06 15:15:16 首次发布

本文链接 https://www.yidiankuaile.com/post/nodejs-jwt-authentication