首页 > 解决方案 > 如何冒泡一个非异步错误

问题描述

我试图冒泡来自 jsonwebtoken 中的验证功能的错误,但是,它将它包装在另一个内部 500 状态错误中,而不是我想要的未经授权的错误中。大多数组件都内置在 loopback-next 身份验证组件中。下面的类是一个名为 AuthenticationStrategy 的类的提供者。AuthenticationStrategy 只是一个带有护照策略的类,它返回一个身份验证策略,该策略在路由的元数据上传递。在下面的类中(Authentication策略类型的provider,value()是调用provider时返回的函数。护照策略验证函数要先转换成Authentication策略,再通过value函数返回给Provider。当 value() 被调用时,验证函数在路由的元数据上运行,在这种情况下,是承载令牌。下面的函数cb与普通护照策略中的‘done’函数相同,分别返回(error, object)

 import {AuthenticateErrorKeys} from '../error-keys';
import {RevokedTokenRepository, UserRepository} from '../../../repositories';
import {repository} from '@loopback/repository';
import {Strategy} from 'passport-http-bearer'
import {HttpErrors} from '@loopback/rest';
import {StrategyAdapter} from '@loopback/authentication-passport'
import {AuthenticationStrategy} from '@loopback/authentication'
import {inject, Provider} from '@loopback/context'
var verify = require('jsonwebtoken').verify

export const BEARER_AUTH_STRATEGY = 'bearer';
export class PassportBearerAuthProvider implements Provider<AuthenticationStrategy> {
  constructor(
    @repository(RevokedTokenRepository)
    public revokedTokenRepository: RevokedTokenRepository,
      @repository(UserRepository)
    public userRepository: UserRepository,
  ){}
  value(): AuthenticationStrategy {
      const bearerStrategy = new Strategy(this.verify.bind(this));
      return this.convertToAuthStrategy(bearerStrategy);
  }

   async verify (token: string, cb: Function){
     try{
      if (token && (await this.revokedTokenRepository.get(token))) {
          throw new HttpErrors.Unauthorized(AuthenticateErrorKeys.TokenRevoked);
        }

        const userAuthToken = await verify(token, process.env.JWT_SECRET as string, {
          issuer: process.env.JWT_ISSUER,
        })

        let authUser = await this.userRepository.getAuthUser(userAuthToken.id)
        return cb(null, authUser)
      }
      catch(error) {
        if (error.name && error.name === "JsonWebTokenError") {
          return cb(new HttpErrors.Unauthorized(AuthenticateErrorKeys.TokenInvalid), null)
        }
        if (error.name && error.name === "TokenExpiredError") {
          return cb(new HttpErrors.Unauthorized(AuthenticateErrorKeys.TokenExpired), null)
        }
        if (error.code && error.code === "ENTITY_NOT_FOUND") {
          return cb(new HttpErrors.Unauthorized(`${AuthenticateErrorKeys.UserDoesNotExist}, id: ${error.entityId}`), null)
        }
        return cb(error, null)
      }
     }


  // Applies the `StrategyAdapter` to the configured basic strategy instance.
  // You'd better define your strategy name as a constant, like
  // `const AUTH_STRATEGY_NAME = 'basic'`
  // You will need to decorate the APIs later with the same name
  convertToAuthStrategy(bearer: Strategy): AuthenticationStrategy {
    return new StrategyAdapter(bearer,BEARER_AUTH_STRATEGY);
  }
}


每次有人发出 API 请求时,都会运行以下序列。如果在路由之上,则使用@authenticate[BEARER_AUTH_TOKEN] 修饰路由,调用上面的提供者,并在元数据上运行验证函数。


export class MySequence implements SequenceHandler {
  constructor(
    @inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
    @inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams,
    @inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
    @inject(SequenceActions.SEND) public send: Send,
    @inject(SequenceActions.REJECT) public reject: Reject,
    @inject(AuthorizationBindings.AUTHORIZE_ACTION)
    protected checkAuthorisation: AuthorizeFn,
     @inject(AuthenticationBindings.AUTH_ACTION)
    protected authenticateRequest: AuthenticateFn,
  ) {}

  async handle(context: RequestContext) {
    try {
      const {request, response} = context;

      const route = this.findRoute(request);
       const args = await this.parseParams(request, route)
      const authUser  = await this.authenticateRequest(request).catch(error => {
        Object.assign(error, {statusCode: 401, name: "NotAllowedAccess", message: (error.message && error.message.message)? error.message.message: "Unable to Authenticate User" });
        throw error
      })
      console.log(authUser)
      const isAccessAllowed: boolean = await this.checkAuthorisation(
        authUser && authUser.permissions,
        request,
      );
      if (!isAccessAllowed) {
        throw new HttpErrors.Forbidden(AuthorizeErrorKeys.NotAllowedAccess);
      }
      const result = await this.invoke(route, args);
      this.send(response, result);
    } catch (error) {
      this.reject(context, error);
    }
  }
}

但是当它捕获到错误时,状态为 500,并且 401 Unauthorized 错误包含在 Internal Status 错误中。我怎样才能返回 401 错误?我有更多这样的情况,其中错误更深,所以我试图进行严格的实施。

标签: javascripttry-catches6-promise

解决方案


推荐阅读