Note
cookie-parser
NodeJS处理cookie的第三方库
发布于 更新于
安装和引入
npm install cookie-parser
// 类型识别
npm install --save-dev @types/cookie-parser
import { ConfigService } from '@nestjs/config';
// cookie-parser 用于解析浏览器请求中携带的 Cookie。
import cookieParser from 'cookie-parser';
配置
在 main.ts中的 bootstrap 配置
async function bootstrap() {
const app = await NestFactory.create(AppModule, {});
}
// 注册 Cookie 解析中间件。
// 注册后,可以通过 request.cookies 读取浏览器发送过来的 Cookie。
app.use(cookieParser());
const configService = app.get(ConfigService);
// 如果前端和后端不是同一个源,例如:
// 前端:http://localhost:5173
// 后端:http://localhost:3000
// 就需要允许跨域请求携带 Cookie。
app.enableCors({
// 指定允许访问后端的前端地址。
// 携带 Cookie 时不能写成 "*"。建议使用环境变量
origin: configService.getOrThrow<string>("FRONTEND_ORIGIN"),
// 允许浏览器在跨域请求中接收和发送 Cookie。
credentials: true,
});
在 Controller 中配置
import { ConfigService } from "@nestjs/config";
// CookieOptions 是 Cookie 配置项的类型。
import type { CookieOptions, Request, Response } from "express";
// Cookie 在浏览器中保存时使用的名字。
const REFRESH_TOKEN_COOKIE_NAME = "refresh_token";
// Cookie 在浏览器中保存 7 天,单位是毫秒。
// 这里要和 JWT_REFRESH_EXPIRES_IN=7d 保持一致。
const REFRESH_TOKEN_COOKIE_MAX_AGE = 7 * 24 * 60 * 60 * 1000;
@Controller("auth")
export class AuthController {
constructor(
private readonly authService: AuthService,
private readonly configService: ConfigService,
) {}
/**
* 返回 refresh token Cookie 的公共配置。
*/
private getRefreshTokenCookieOptions(): CookieOptions {
// 生产环境一般使用 HTTPS,因此生产环境开启 Secure。
const isProduction =
this.configService.get<string>("NODE_ENV") === "production";
return {
// HttpOnly 禁止前端 JavaScript 通过 document.cookie 读取 refresh token。
// 这可以降低 XSS 攻击直接窃取 refresh token 的风险。
httpOnly: true,
// Secure 表示只允许浏览器通过 HTTPS 发送这个 Cookie。
// 本地开发通常使用 HTTP,所以开发环境设为 false。
secure: isProduction,
// Lax 可以阻止大部分跨站请求携带 Cookie,从而降低 CSRF 风险。
// 前后端只是端口不同或使用同一主域名时,一般可以使用 Lax。
sameSite: "lax",
// 限制 Cookie 只发送给 /auth 路径下的接口。
// 这样访问普通业务接口时不会携带 refresh token。
path: "/auth",
// 浏览器保存 Cookie 的时间,这里的单位是毫秒。
maxAge: REFRESH_TOKEN_COOKIE_MAX_AGE,
};
}
/**
* 把 refresh token 写入 HttpOnly Cookie。
*/
private setRefreshTokenCookie(
response: Response,
refreshToken: string,
): void {
// response.cookie() 会在响应头中添加 Set-Cookie。
// refresh token 不会出现在 Controller 返回的 JSON 数据里。
response.cookie(
REFRESH_TOKEN_COOKIE_NAME,
refreshToken,
this.getRefreshTokenCookieOptions(),
);
}
}