You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建verifyTokenAdmin中间件报错:Request类型不存在users属性

解决Express + TypeScript中扩展Request对象类型的问题

我需要实现两个Express中间件:一个负责用户认证,另一个校验用户的isAdmin字段是否为true(管理员权限校验)。认证中间件原本运行正常,但为了让管理员中间件能获取用户信息,我在认证中间件中添加了req.users = data;,随即触发TypeScript错误:

Property 'users' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.ts(2339)

在管理员中间件中访问req.users时,也出现了完全相同的错误。


认证中间件代码

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';

interface TokenPayload {
  id: string;
  iat: number;
  exp: number;
}

export default async function authMiddleware(
  req: Request, res: Response, next: NextFunction
) {
  const { authorization } = req.headers;

  if (!authorization) {
    return res.status(401).json('无效的授权信息');
  };

  const token = authorization.replace('Bearer', ' ').trim();

  try {
    const secret = process.env.JWT_SECRET as string;
    const data = jwt.verify(token, secret);

    req.users = data;

    const { id } = data as TokenPayload;

    req.userId = id;

    return next();
  } catch (err) {
    return res.status(401).json(err);
  }
}

管理员校验中间件代码

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import authMiddleware from './AuthMiddlewares';

export default async function authAdminMiddleware(
  req: Request, res: Response, next: NextFunction,
) {
  authMiddleware(req, res, () => {
    if (req.users.isAdmin) {
      next();
    } else {
      res.status(403).json("你没有权限执行此操作!");
    }
  })
}

解决方案

1. 扩展Express的Request类型声明

TypeScript默认的Request类型没有users和userId属性,需要手动扩展。在项目中创建一个类型声明文件(比如types/express.d.ts),内容如下:

import { Request } from 'express';

// 定义JWT解析后的用户数据结构,包含管理员字段
interface AuthenticatedUser {
  id: string;
  iat: number;
  exp: number;
  isAdmin: boolean; // 对应数据库中的isAdmin字段
}

declare global {
  namespace Express {
    interface Request {
      users: AuthenticatedUser; // 为Request添加users属性
      userId: string; // 同时添加你用到的userId属性
    }
  }
}

2. 确保TypeScript识别自定义类型

修改tsconfig.json,让TypeScript能读取到刚才创建的类型文件:

{
  "compilerOptions": {
    // 其他编译配置...
    "typeRoots": ["./node_modules/@types", "./types"]
  },
  "include": ["src/**/*", "types/**/*"]
}

3. 修正认证中间件的类型断言

jwt.verify返回的是unknown类型,需要明确断言为我们定义的AuthenticatedUser:

// 替换原来的data赋值逻辑
const data = jwt.verify(token, secret) as AuthenticatedUser;
req.users = data;
req.userId = data.id;

4. 优化管理员中间件的权限校验逻辑(可选但推荐)

建议从数据库查询最新的用户信息进行权限校验,避免JWT签发后用户权限被修改但令牌仍有效的问题:

import { Request, Response, NextFunction } from 'express';
import authMiddleware from './AuthMiddlewares';
// 假设你有用户模型
import UserModel from '../models/User';

export default async function authAdminMiddleware(
  req: Request, res: Response, next: NextFunction,
) {
  authMiddleware(req, res, async () => {
    // 从数据库获取最新用户信息
    const user = await UserModel.findById(req.userId);
    if (!user) {
      return res.status(404).json("用户不存在");
    }
    if (user.isAdmin) {
      next();
    } else {
      res.status(403).json("你没有权限执行此操作!");
    }
  });
}

内容的提问来源于stack exchange,提问作者Routfin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:15:42