没有在 typescript 装饰器中执行 express-jwt 中间件

问题描述

我为 express 编写了自定义装饰器。这是控制器装饰器:

export function controller(routePrefix: string) {
  return function (target: Function) {
    const router = AppRouter.getInstance();
    for (let key in target.prototype) {
      const routeHandler = target.prototype[key]; //getLogin
      const path = Reflect.getMetadata(
        MetadataKeys.Path,target.prototype,key
      );
      const method: Methods = Reflect.getMetadata(
        MetadataKeys.Method,key
      );
      const middlewares =
        Reflect.getMetadata(MetadataKeys.Middleware,key) ||
        [];
      if (path) {
        router[method](
          `${routePrefix}${path}`,...middlewares,routeHandler
        );
      }
    }
  };
}

这是 use 装饰器:

export function use(middleware: RequestHandler | jwtRequestHandler) {
  return function (target: any,key: string,desc: PropertyDescriptor) {
    const middlewares =
      Reflect.getMetadata(MetadataKeys.Middleware,target,key) || [];
    Reflect.defineMetadata(
      MetadataKeys.Middleware,[...middlewares,middleware],key
    );
  };
}

路线如下:

@controller("/api/v1/portfolios")

@post("/")
  @use(checkJwt)
  @use(checkRole("admin"))
  async createPortfolio(req: Request,res: Response) {
    const portfolioData = req.body;
    console.log("portfoliodata",portfolioData);
    const userId = req.user.sub;
    const portfolio = new Portfolio(portfolioData);
    console.log("portfoliom");
    portfolio.userId = userId;
}

express-jwt 接受请求并将 user 添加到请求对象中。

`user=req.user`

这里是 checkJwt 中间件:

export const checkJwt = jwt({
  secret: jwksRsa.expressJwtSecret({
    cache: true,rateLimit: true,jwksRequestsPerMinute: 10,// this link is always provided by auth0 providers
    jwksUri: process.env.JWKS_URI as string,}),//   this is in the API/identifier in auth0.com
  audience: process.env.AUTH0_AUDIENCE,//   issuer should end with "/"
  issuer: process.env.ISSUER,algorithms: ["RS256"],});

但是 checkJwt 没有被执行。 checkRole 被执行,所以这意味着我的设置是正确的。由于未执行 checkJwt,因此未定义 req.user,因此 checkRole 会捕获错误。这是checkRole

export const checkRole = (role: string) => (
  req: Request,res: Response,next: NextFunction
) => {
  let user: { [key: string]: string } = {};
  user = req.user;
  if (user && user[process.env.AUTH0_NAMESPACE + "/roles"].includes(role)) {
    next();
  } else {
    return res
      .status(401)
      .send("You are not authorized to access this resource!");
  }
};

当我从客户发布投资组合时,checkRole 发送此错误“您无权访问此资源!”。

我不知道如何让 express 执行 checkJwt。

解决方法

你需要注意你的装饰器的顺序。 The documentation 表示装饰器从上到下调用​​,但结果从下到上返回。

所以你的代码应该是这样的:

@post("/")
@use(checkRole("admin"))
@use(checkJwt)
async createPortfolio(req: Request,res: Response) {
   //Your code
}