javascript - 如何冒泡一个非异步错误
问题描述
我试图冒泡来自 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 错误?我有更多这样的情况,其中错误更深,所以我试图进行严格的实施。
解决方案
推荐阅读
- python - 将数据帧索引移动一定数量
- python - 根据条件使用多索引更新熊猫数据框
- c - Visual Studio 编译错误退出状态 1
- java - 如何在 Java 中使用带有 CriteriaBuilder 的 sql 函数?
- python - python中的.doc到.docx的转换
- typescript - 更新的状态未反映在我的 onPress 事件中
- c# - C# - DSharp 获得 Bots(最高)角色的颜色
- ios - 在 SwiftUI 中将绑定传递给导航堆栈中每个视图的最佳方法是什么
- clean-architecture - 清洁架构 - 存储库是网关?如果是对的,一个用例可以直接调用一个存储库吗?
- git - git rebase,压缩所有提交:如何发生冲突?