feat(server): 安全基线(Helmet+限流+脱敏)(E10)
- 注册 @fastify/helmet(CSP 关闭) - 引入 @fastify/rate-limit,并对 login/forgot/reset 按开关启用 - Fastify logger 增加敏感字段 redaction(authorization/cookie/password 等)
这个提交包含在:
+11
-3
@@ -39,7 +39,15 @@ async function authRoutes(fastify) {
|
||||
password: z.string().min(1),
|
||||
});
|
||||
|
||||
fastify.post("/login", async (request, reply) => {
|
||||
const authRateLimit =
|
||||
fastify.config.rateLimitEnabled && typeof fastify.rateLimit === "function"
|
||||
? fastify.rateLimit({
|
||||
max: fastify.config.rateLimitLoginMax,
|
||||
timeWindow: fastify.config.rateLimitLoginWindow,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
fastify.post("/login", { preHandler: authRateLimit }, async (request, reply) => {
|
||||
const parsed = loginBodySchema.safeParse(request.body);
|
||||
if (!parsed.success) {
|
||||
throw new AppError({
|
||||
@@ -374,7 +382,7 @@ async function authRoutes(fastify) {
|
||||
email: z.string().email(),
|
||||
});
|
||||
|
||||
fastify.post("/forgot-password", async (request, reply) => {
|
||||
fastify.post("/forgot-password", { preHandler: authRateLimit }, async (request, reply) => {
|
||||
const parsed = forgotPasswordBodySchema.safeParse(request.body);
|
||||
if (!parsed.success) {
|
||||
throw new AppError({
|
||||
@@ -436,7 +444,7 @@ async function authRoutes(fastify) {
|
||||
newPassword: z.string().min(12),
|
||||
});
|
||||
|
||||
fastify.post("/reset-password", async (request, reply) => {
|
||||
fastify.post("/reset-password", { preHandler: authRateLimit }, async (request, reply) => {
|
||||
const parsed = resetPasswordBodySchema.safeParse(request.body);
|
||||
if (!parsed.success) {
|
||||
throw new AppError({
|
||||
|
||||
在新工单中引用
屏蔽一个用户