我在NestJS中有以下两个保护(一个用于基于API密钥的身份验证,另一个用于基于令牌的身份验证)。ApiKeyGuard是最优先的。我想实现一个系统,如果任何人有一个密钥,它不会检查其他保护。有没有什么方法可以使AuthGuard可选的基础上,第一个保护是否通过的情况下,有一个ApiKeyGuard?
// Can be accessed with token within app as well as third party users
@UseGuards(ApiKeyGuard, AuthGuard)
@Get('/get-products')
async getProducts(): Promise<any> {
try {
return this.moduleRef
.get(`appService`, { strict: false })
.getProducts();
} catch (error) {
throw new InternalServerErrorException(error.message, error.status);
}
}
// Only to be accessed with token within app
@UseGuards(AuthGuard)
@Get('/get-users')
async getUsers(): Promise<any> {
try {
return this.moduleRef
.get(`appService`, { strict: false })
.getUsers();
} catch (error) {
throw new InternalServerErrorException(error.message, error.status);
}
}
下面的保护用于检查基于API密钥的身份验证。
api-key.guard.ts
@Injectable()
export class ApiKeyGuard implements CanActivate {
constructor(private readonly apiKeyService: ApiKeyService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const req = context.switchToHttp().getRequest();
const key = req.headers['X-API-KEY'] ?? req.query.api_key;
return this.apiKeyService.isKeyValid(key);
}
下面的保护用于检查基于令牌的身份验证
authentication.guard.ts
@Injectable()
export class AuthGuard implements CanActivate, OnModuleInit {
constructor(private readonly moduleRef: ModuleRef) {}
onModuleInit() {}
async canActivate(context: ExecutionContext): Promise<boolean> {
try {
// Get request data and validate token
const request = context.switchToHttp().getRequest();
if (request.headers.authorization) {
const token = request.headers.authorization.split(' ')[1];
const response = await this.checkToken(token);
if (response) {
return response;
} else {
throw new UnauthorizedException();
}
} else {
throw new UnauthorizedException();
}
} catch (error) {
throw new UnauthorizedException();
}
}
}
1条答案
按热度按时间nimxete21#
我所做的是使用@nestjs/passport和使用
AuthGuard
并定制PassportJS策略。我遇到了类似的问题,并寻找一种方法来完成这一点,而不使用一些“魔术”。documentation can be found here。在
AuthGuard
中,你可以添加多个保护。虽然它非常强大,但在文档中有点隐藏。请看这里,特别是该部分的最后一行,它声明:除了扩展默认的错误处理和身份验证逻辑之外,我们还可以允许身份验证通过一个策略链。第一个成功的策略、重定向或错误将中止该链。身份验证失败将依次通过每个策略,如果所有策略都失败,则最终失败。
可以这样做:
现在,回到您的示例,您必须创建2个自定义策略,一个用于API密钥,一个用于授权头,并且这两个保护都应该被激活。
因此,对于API策略(作为示例):
对其他身份验证方法执行类似的操作,然后按如下所示使用Passport防护:
这样,守卫会尝试所有的策略(按顺序),当所有策略都失败时,你的身份验证失败。如果其中一个成功,你就通过了身份验证!