创建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
相关产品推荐
相关产品推荐

