Frontend Technical Notes
info
学习并记录 General Frontend Questions
Node.js & CommonJS
1. What is require function in Node.js?
什么是 require?
require()是 CommonJS 的模块加载函数,在 运行时 同步读取、解析与执行目标模块(.js/.json/.node),返回其module.exports。- Node 会做路径解析、文件定位、编译包裹(function wrapper)、并将结果缓存在
require.cache里(同进程二次加载走缓存)。
const fs = require('fs'); // 内置模块
const express = require('express'); // 第三方包
const util = require('./utils'); // 本地文件
const config = require('./config.json'); // JSON 自动解析
// 导出
module.exports = { foo, bar };
2. What is buffer in Node.js?
- 定义: Buffer 是 Node.js 提供的 二进制数据容器(类似字节数组),常用于 流(文件 I/O、TCP、加密、压缩等)。
- 关键点: 固定长度、在 V8 堆外申请内存;与 fs、net、crypto 等 API 深度结合.
// 1. 创建 Buffer
const buf1 = Buffer.from('Hello'); // 从字符串创建
console.log(buf1.toString()); // "Hello"
// 2. 分配固定大小 Buffer
const buf2 = Buffer.alloc(5); // 分配 5 字节,默认全 0
console.log(buf2); // <Buffer 00 00 00 00 00>
// 3. Buffer 拼接
const b1 = Buffer.from('Node');
const b2 = Buffer.from('JS');
const combined = Buffer.concat([b1, b2]);
console.log(combined.toString()); // "NodeJS"
// 4. 编码/解码
const buf3 = Buffer.from('测试');
console.log(buf3.toString('utf8')); // "测试"
console.log(buf3.toString('hex')); // 十六进制形式
3. 在 Node.js 实现 Authentication & Authorization
- 1.注册 Register
- 接收用户信息,
bcrypt.hash加密密码,存入数据库。
- 接收用户信息,
- 2.登录 Login
- 验证邮箱+密码正确性。
- 成功后签发两个令牌:
- Access Token (短有效期,如 15 分钟) -> 放
sub、role信息 - Refresh Token (长有效期,如 7 天) -> 存入
refreshTokens[]以便后续刷新
- Access Token (短有效期,如 15 分钟) -> 放
- 3.认证 Authentication
- 中间件解析
Authorization: Bearer <token>。 - 用
jwt.verify校验有效性,挂载req.user。
- 中间件解析
- 4.鉴权 Authorization
- 使用中间件实现 例如 基于角色控制访问权限
- 判断用户
role/scope是否有权限访问 - 若角色不匹配 → 返回
403 Forbidden
- 5.刷新 Refresh
- 客户端提交
refreshToken到/refresh - 判断该 token 是否存在于
refreshTokens[] - 通过验证后重新签发一个新的 Access Token
- 确保 Access Token 始终是短有效期,提高安全性
- 客户端提交
- 6.登出 Logout
- 客户端提交
refreshToken。 - 从
refreshTokens[]中删除该 token,实现 逐端登出. - 返回
{ message: '已登出' }。
- 客户端提交
// 安装依赖:npm install express bcrypt jsonwebtoken
const express = require('express');
const bcrypt = require('bcrypt'); // 用于密码哈希
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
const SECRET = 'my-secret-key'; // 生产环境要放在环境变量里
let users = []; // 模拟数据库
let refreshTokens = []; // 存储 Refresh Token(真实项目可放 DB/Redis)
// 1. 注册:密码哈希存储
app.post('/register', async (req, res) => {
const { email, password } = req.body;
// 对密码做哈希,10 表示 saltRounds
const hashedPassword = await bcrypt.hash(password, 10);
users.push({ email, password: hashedPassword, role: 'user' });
res.json({ message: '用户注册成功' });
});
// 2. 登录:验证凭证并签发 JWT
app.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = users.find(u => u.email === email);
if (!user) return res.status(400).json({ message: '用户不存在' });
const valid = await bcrypt.compare(password, user.password);
if (!valid) return res.status(401).json({ message: '密码错误' });
// Access Token:短有效期(如 15 分钟)
const accessToken = jwt.sign(
{ sub: email, role: user.role },
SECRET,
{ expiresIn: '15m' }
);
// Refresh Token:有效期长,可撤销
const refreshToken = jwt.sign({ sub: email }, SECRET, { expiresIn: '7d' });
refreshTokens.push(refreshToken);
res.json({ accessToken, refreshToken });
});
// 3. 认证中间件:解 析并验证 JWT
function authenticate(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // "Bearer <token>"
if (!token) return res.sendStatus(401);
jwt.verify(token, SECRET, (err, user) => {
if (err) return res.sendStatus(403); // token 过期/无效
req.user = user; // 把解码后的 payload 挂到 req 上
next();
});
}
// 4. 鉴权(授权):基于角色控制访问
function authorizeRole(role) {
return (req, res, next) => {
if (req.user.role !== role) return res.sendStatus(403);
next();
};
}
// 受保护路由:只有登录用户能访问
app.get('/profile', authenticate, (req, res) => {
res.json({ email: req.user.sub, role: req.user.role });
});
// 管理员专属路由
app.get('/admin', authenticate, authorizeRole('admin'), (req, res) => {
res.json({ message: '只有管理员能看到的内容' });
});
// 5. 刷新 Access Token
app.post('/refresh', (req, res) => {
const { token } = req.body;
if (!token || !refreshTokens.includes(token)) return res.sendStatus(403);
jwt.verify(token, SECRET, (err, user) => {
if (err) return res.sendStatus(403);
const newAccessToken = jwt.sign({ sub: user.sub, role: user.role }, SECRET, { expiresIn: '15m' });
res.json({ accessToken: newAccessToken });
});
});
// 6. 登出:移除 Refresh Token(逐端登出)
app.post('/logout', (req, res) => {
const { token } = req.body;
refreshTokens = refreshTokens.filter(t => t !== token);
res.json({ message: '已登出' });
});
app.listen(3000, () => console.log('Server running on port 3000'));