使用 Fastify preHandler 中间件

问题描述 投票:0回答:2

在访问此路由之前通过中间件对用户进行身份验证。

当我将

tokenController.authUser
作为中间件
tokenService
传递给
tokenController
时,是
undefined
。但是,当我将此方法作为路由内的函数而不是中间件运行时,它工作得很好。

server.post('/api/admin/test', { preHandler: [tokenController.authUser] }, async (request: any, reply: any) => {
    return null
});

令牌控制器:-

import { Users } from "@prisma/client";
import ITokenService from "../../services/tokenService/ITokenService";
import ITokenController from "./ITokenController";

export default class TokenController implements ITokenController {
    private readonly tokenService: ITokenService;
    constructor(_tokenService: ITokenService) {
        this.tokenService = _tokenService;
    }

    async authUser(request: any, reply: any): Promise<Users | Error> {
        const authHeader = request.headers['authorization'];
        const token = authHeader && authHeader.split(' ')[1];
        if (token === null)
            return reply.code(401);
        try {
            const result = await this.tokenService.verifyToken(token);
            console.log(result);
            return result;
        }
        catch (e) {
            reply.code(401);
            return new Error("Error");
        }
    }
}

代币服务:-

import { Users } from "@prisma/client";
import ITokenService from "./ITokenService";

export default class TokenService implements ITokenService {
    private readonly sign: Function;
    private readonly verify: Function;
    private readonly secretKey: string;
    constructor(sign: Function, verify: Function, _secretKey: string) {
        this.sign = sign;
        this.verify = verify;
        this.secretKey = _secretKey;
    }

    public async generateToken(user: Users): Promise<string> {
        return await this.sign({ user }, this.secretKey);
    }

    public async verifyToken(token: string): Promise<Users | Error> {
        const result = await this.verify(token, this.secretKey);
        return result;
    }
}

node.js typescript middleware clean-architecture fastify
2个回答
5
投票

出于某种原因,制作一个单独的中间件函数并在该方法内调用

tokenController.authUser
效果很好。

const middleware = (_req, _res, next) => {
  console.log('middleware');
  next()
}


server.post('/api/admin/test', { preHandler: [middleware] }, async (request: any, reply: any) => {
    return null
});

0
投票

这是类方法的常见问题。

当您传递

tokenController.authUser
时,您正在传递一个与它来自的
tokenController
实例断开连接的单独函数。结果,当调用它时,
this
通常指向的对象丢失了(或更可能的是,被替换为
globalThis
),因此
this.mostThings
将是未定义的。

澄清一下:

// Works as expected, because when we call a function this way, the
// JavaScript engine sets this=tokenController during the call
tokenController.authUser(...)

const authUser = tokenController.authUser
// Does not work, because no "this" can be set, so the function body
// cannot "see" tokenController
authUser(...)

常见的解决方案是将

authUser
函数绑定到
tokenController
对象:

server.post('/api/admin/test', {
  preHandler: [tokenController.authUser.bind(tokenController)]
}, ...)

另一种方法是每次都直接打电话给

tokenController.authUser()

const boundAuthUser = function(...args) {
  tokenController.authUser(...args)
}

server.post('/api/admin/test', { preHandler: [boundAuthUser] }, ...)
© www.soinside.com 2019 - 2024. All rights reserved.