还只会express?今儿使用Koa2 实现 Jwt鉴权

Jwt认识

Jwt (JSON Web Token),是客户端和服务端进行通信 ,服务器向用户发送的 JSON对象。

因为http是一种无状态协议。每次连接完成后,两端(客户端和服务端)完成资源传输后关闭,再次交互时重新建立新的连接。服务端无法跟踪上次用户访问的相同资源。

于是又token 或是 cookie 认证,极大增强交互和安全性

这样使用cookie 认证流程:

  • 这时候使用cookie(未到期)一种文本形式,在浏览器端存储(内存或硬盘)。如果用户访问过,服务端会根据浏览器带上的cookie 凭据进行 验证【cookie 实现一般通过定义http请求头或 set-cookie 的响应头 】
  • 用户向服务器发送用户名和密码等信息
  • 服务器验证通过后,在当前对话(session)保存相关数据,比如:用户角色、登入信息等
  • 用户第一次访问,服务器会记录这次的对话sessionId,并将这个记录通过cookie返回给浏览器
  • 用户下次访问时,浏览器带上cookie 和sessionId进行比配,是否正确
  • 注意:cookie 一般存在浏览器。而session 相对安全得 存在服务器,如果过期,服务器有自动回收session 会话机制

JWT 的数据结构

JWT 的三个部分依次如下:

  • Header(头部),类似如下
json 复制代码
{
  "alg": "HS256",
  "typ": "JWT"
}

alg 属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256)。typ 属性表示这个令牌(token)的类型(type),JWT 令牌统一写为 JWT

  • Payload(负载)。也是一个 JSON,用来存放实际需要传递的数据。JWT 规定了 7 个官方字段。如下所示
  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

当然也可以自定义私有字段。但是要注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

  • Signature(签名)。Signature 部分是对前两部分的签名,防止数据篡改。首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
scss 复制代码
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

算出签名以后,把 HeaderPayloadSignature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户

现在使用Koa2 进行搭建

我们要用 Koa2 搭一个简单的用户系统,关键功能就两个:

  1. 用户登录,服务端给个 token,客户端拿着。
  2. 下次请求,客户端把 token 交给服务端,服务端验一下,没问题就给数据,不行就报错(401)。
  • 用到的库:
    • jsonwebtoken:生成和校验 token 的主力。
    • koa-jwt:把 jsonwebtoken 封装一下,方便在 Koa2 里用,主要是用来校验 token。
    • axios:前端发请求用的,顺便用它的拦截器处理请求数据。

三、项目结构

bash 复制代码
koa-jwt-demo/
├── package.json
├── app.js
├── controllers/
│   ├── user.js
│   └── home.js
├── middlewares/
│   └── error.js
├── routes/
│   └── index.js
└── utils/
    └── jwt.js

四、动手搭建

在项目根目录下运行以下命令安装必要的依赖:

bash 复制代码
npm install koa koa-router koa-bodyparser koa-jwt jsonwebtoken bcryptjs

1. 初始化项目

先搭个架子,跑起来再说。

Koa 本身不解析请求体,但可以通过 koa-bodykoa-bodyparser 中间件实现。

app.js

JavaScript 复制代码
// app.js
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');
const jwt = require('koa-jwt');
const { secret } = require('./utils/jwt'); // JWT 密钥
const errorMiddleware = require('./middlewares/error'); // 错误处理中间件
const routes = require('./routes'); // 路由配置

const app = new Koa();

// 错误处理中间件
app.use(errorMiddleware);

// 解析请求体
app.use(bodyParser());

// JWT 鉴权中间件
app.use(jwt({ secret }).unless({ path: [/^\/api\/auth/]})); // 除了 /api/auth 路径外,其他路径都需要 JWT 鉴权

// 挂载路由
app.use(routes.routes());
app.use(routes.allowedMethods());

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

2. 错误处理中间件

出错别慌,这里兜底。

下面使用Koa 中间件next,用于处理请求和响应。中间件可以使用async / await,执行顺序遵循"洋葱模型",即先递归到最内层,再逐层回溯

middlewares/error.js

JavaScript 复制代码
module.exports = async (ctx, next) => {
    try {
        await next();
    } catch (err) {
        ctx.status = err.status || 500;
        ctx.body = { message: err.message };
    }
};

3. JWT 工具函数

生成 token,校验 token,全靠它。

utils/jwt.js

JavaScript 复制代码
// utils/jwt.js
const jwt = require('jsonwebtoken');

const secret = 'your_jwt_secret'; // JWT 密钥

// 生成 JWT 令牌
const generateToken = (user) => {
    return jwt.sign(user, secret, { expiresIn: '1h' }); // 令牌有效期为 1 小时
};

module.exports = { secret, generateToken };

4. 用户控制器

用户注册、登录,搞定。

controllers/user.js

JavaScript 复制代码
// controllers/user.js
const bcrypt = require('bcryptjs');
const { generateToken } = require('../utils/jwt');

const users = []; // 模拟用户存储

// 用户注册
const register = async (ctx) => {
    const { username, password } = ctx.request.body;
    const hashedPassword = await bcrypt.hash(password, 10); // 加密密码
    users.push({ username, password: hashedPassword });
    ctx.body = { message: 'User registered successfully' };
};

// 用户登录
const login = async (ctx) => {
    const { username, password } = ctx.request.body;
    const user = users.find(u => u.username === username);
    if (!user || !(await bcrypt.compare(password, user.password))) {
        ctx.status = 401;
        ctx.body = { message: 'Invalid credentials' };
        return;
    }
    const token = generateToken({ username }); // 生成 JWT 令牌
    ctx.body = { token };
};

module.exports = { register, login };

5. 主页控制器

受保护的资源,拿 token 才能进,koa可以使用ctx 设置body,satus等响应内容

controllers/home.js

JavaScript 复制代码
const home = (ctx) => {
    ctx.body = { message: 'Welcome to the protected area' };
};

module.exports = { home };

6. 路由配置

Koa 本身不内置路由功能,但可以通过 koa-router 插件实现

routes/index.js

JavaScript 复制代码
// routes/index.js
const Router = require('koa-router');
const { register, login } = require('../controllers/user');
const { home } = require('../controllers/home');

const router = new Router({ prefix: '/api' });

// 用户注册
router.post('/auth/register', register);

// 用户登录
router.post('/auth/login', login);

// 受保护的资源
router.get('/home', home);

module.exports = router;

五、前端请求拦截器

前端用 axios,每次请求带上 token。

JavaScript 复制代码
import axios from 'axios';

axios.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    config.headers.common['Authorization'] = 'Bearer ' + token;
    return config;
});

六、跑起来试试

  1. 启动服务:node app.js

  2. 测试:

    • 注册:POST http://localhost:3000/api/auth/register,带个 { "username": "testuser", "password": "password" }
    • 登录:POST http://localhost:3000/api/auth/login,用刚才的账号密码。
    • 拿到 token,存到 localStorage 里。
    • 访问:GET http://localhost:3000/api/home,看能不能拿到欢迎信息。

七、总结

这个项目就是个"麻雀虽小,五脏俱全"的例子,把 Koa2、JWT 鉴权、错误处理这些关键点都串起来了。JWT 的流程也很清晰:登录拿 token,请求带 token,服务端验 token,搞定!

希望这个实战例子能让你快速上手,要是遇到啥问题,直接问,别客气!

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax