{T}

后端模块

redis

code
npm install redis

封装 redis

javascript
import { createClient } from "redis"
import { REDIS } from "./index"
import retryStrategy from "node-redis-retry-strategy"

const options = {
  password: REDIS.password,
  socket: {
    host: REDIS.host,
    port: REDIS.port,
    detect_buffers: true,
    reconnectStrategy: retryStrategy()
  }
}

const client = createClient(options)

const initRedis = async () => {
  client.on("error", (err) => console.log("Redis Client Error", err))
  await client.connect()

  client.on("end", function () {
    console.log("redis connection has closed")
  })

  client.on("reconnecting", function (o) {
    console.log("redis client reconnecting", o.attempt, o.delay)
  })
}

/**
 * 设置 redis 值
 *
 * @param {*} key 键
 * @param {*} value 值
 * @param {*} time 过期时间
 */
const setValue = async (key, value, time) => {
  if (typeof value === "undefined" || value == null || value === "") {
    return
  }
  if (typeof value === "string") {
    if (typeof time !== "undefined") {
      await client.set(key, value, "EX", time)
    } else {
      await client.set(key, value)
    }
  } else if (typeof value === "object") {
    for (let i = 0; i < Object.keys(value).length; i++) {
      const item = Object.keys(value)[i]
      await client.hset(key, item, value[item], console.log)
    }
  }
}

/**
 * 根据 key 获取 redis 值
 *
 * @param {*} key
 * @return {*}
 */
const getValue = async (key) => {
  return await client.get(key)
}

/**
 * 根据 key 获取 redis 值
 *
 * @param {*} key
 * @return {*}
 */
const getHValue = async (key) => {
  return await client.hgetall(key)
}

const delValue = (key) => {
  client.del(key, (err, res) => {
    if (res === 1) {
      console.log("删除 key 成功")
    } else {
      console.log("删除 redis key 失败:" + err)
    }
  })
}

export { client, setValue, getValue, getHValue, delValue, initRedis }

koa-jwt

koa-jwt 是一个用于 Koa 应用的中间件,负责处理基于 JSON Web Token (JWT) 的身份验证。它可以保护指定的路由,使得只有提供有效 JWT 的请求才能访问这些路由。JWT 是一种用于在客户端和服务器之间安全地传递信息的紧凑、URL 安全的令牌

bash
npm install koa-jwt

koa-jwt 的基本用法是通过在 Koa 应用中使用中间件来保护某些路由。jwt({ secret }) 中间件保护所有后续的路由,只有携带有效 JWT 的请求才能访问

javascript
const Koa = require('koa');
const jwt = require('koa-jwt');
const jsonwebtoken = require('jsonwebtoken');

const app = new Koa();
const secret = 'your-secret-key';

app.use(jwt({ secret }));

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

配置选项

koa-jwt 提供了一些配置选项,可以用于定制 JWT 的处理方式:

  • secret: 用于验证 JWT 的密钥或公钥
  • key: 将解码后的 token 赋值到 ctx.state 的键名,默认为 user
  • tokenKey: 将 token 放在 ctx.state 的键名,默认为 jwtOriginalError
  • cookie: 指定从哪个 cookie 读取 token
  • getToken: 自定义获取 token 的方法
javascript
app.use(jwt({
  secret: 'your-secret-key',
  key: 'auth', // 将解码后的 token 赋值到 ctx.state.auth
  getToken: (ctx) => {
    if (ctx.headers.authorization && ctx.headers.authorization.split(' ')[0] === 'Bearer') {
      return ctx.headers.authorization.split(' ')[1];
    } else if (ctx.query && ctx.query.token) {
      return ctx.query.token;
    }
    return null;
  }
}));

错误处理

默认情况下,如果请求中没有提供有效的 JWT,koa-jwt 会返回 401 Unauthorized 错误。使用 Koa 的错误处理中间件来自定义错误响应:

javascript
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    if (err.status === 401) {
      ctx.status = 401;
      ctx.body = 'Protected resource, use Authorization header to get access\n';
    } else {
      throw err;
    }
  }
});

jsonwebtoken

jsonwebtoken 是一个用于在 Node.js 应用中生成和验证 JSON Web Tokens (JWT) 的库。JWT 是一种紧凑的、URL 安全的令牌格式,广泛用于在 Web 应用中进行用户身份验证和信息交换

bash
npm install jsonwebtoken

基本使用

生成 JWT

生成一个 JWT 需要一个密钥 (secret key) 或者一个私钥 (private key)

  • payload 是你想要在 JWT 中存储的数据
  • secret 是用于签名 JWT 的密钥
  • expiresIn 指定了令牌的有效期,这里设置为 1 小时
javascript
const jwt = require('jsonwebtoken');

const payload = {
  userId: 123,
  username: 'john_doe'
};

const secret = 'your-256-bit-secret'; // 这应该是一个安全的密钥

const token = jwt.sign(payload, secret, { expiresIn: '1h' });

console.log(token);

验证 JWT

使用 jsonwebtoken 验证 JWT 也很简单,需要使用与生成令牌时相同的密钥:

  • token 是你要验证的 JWT
  • secret 是用于验证 JWT 的密钥
  • jwt.verify 方法会验证令牌并返回解码后的 payload。如果令牌无效或已过期,会返回错误
javascript
const jwt = require('jsonwebtoken');

const token = 'your.jwt.token.here';
const secret = 'your-256-bit-secret';

jwt.verify(token, secret, (err, decoded) => {
  if (err) {
    console.error('Token verification failed:', err);
  } else {
    console.log('Decoded payload:', decoded);
  }
});

使用 RSA 或 ECDSA 密钥

除了使用对称加密密钥,还可以使用 RSA 或 ECDSA 密钥对来签名和验证 JWT。下面是一个使用 RSA 私钥和公钥的示例:

RSA 生成 JWT

javascript
const fs = require('fs');
const jwt = require('jsonwebtoken');

const payload = {
  userId: 123,
  username: 'john_doe'
};

const privateKey = fs.readFileSync('path/to/private.key');

const token = jwt.sign(payload, privateKey, { algorithm: 'RS256', expiresIn: '1h' });

console.log(token);

RSA 验证 JWT

javascript
const fs = require('fs');
const jwt = require('jsonwebtoken');

const token = 'your.jwt.token.here';
const publicKey = fs.readFileSync('path/to/public.key');

jwt.verify(token, publicKey, { algorithms: ['RS256'] }, (err, decoded) => {
  if (err) {
    console.error('Token verification failed:', err);
  } else {
    console.log('Decoded payload:', decoded);
  }
});