![](/img/trans.png)
[英]User is undefined on the context.switchToHttp().getRequest() nestjs
[英]NestJs - Unable to get user context in RolesGuard
我使用 NestJS 作為客戶端 API 的框架。 在框架內,我們使用了一個運行良好的非常標准的 Passport/JWT 身份驗證基礎設施。 當找到承載令牌時,我們的 AuthGuard 正在觸發,並且在安全的 API 端點中,我可以通過“@Res() 請求”注入 HTTP 上下文並訪問包含我的 Z794349 令牌的有效負載的“request.user”屬性.
最重要的是,我們正在嘗試以與文檔中提供的示例代碼和 GitHub 上的一些示例項目非常相似的方式實現“RolesGuard”(其中沒有一個實際使用此防護,但它們將其包含為示例防護)。
我們的問題是,我們的 AuthGuard 觸發並驗證 Jwt 令牌,然后我們的 RolesGuard 觸發,但它傳遞的請求 object 沒有附加到請求的用戶元數據。
我們 RolesGuard 中的關鍵代碼是:
const request = context.switchToHttp().getRequest();
const user = request.user;
if (!user) {
return false;
}
在上面的截圖中,用戶總是假的。 是否有人在 Nest 中編寫了基於角色/權限的守衛,成功訪問了當前用戶的 scope? 所有代碼都在觸發,並且所有內容都顯示正確注冊。
-凱文
最終,這似乎是守衛的排序問題,而且看起來不容易解決(沒有框架允許對排序進行一些控制)。
我的希望是全局注冊 RolesGuard,但這會導致它首先注冊並首先觸發。
@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles('admin')
如果我在端點級別注冊它並將其放在 AuthGuard 之后,那么它會第二次觸發,並且我會在警衛本身中獲得我期望的用戶上下文。 它並不完美,但它有效。
-凱文
在端點級別注冊 RoleGuard 並將其放在 AuthGuard 之后,然后它會觸發第二次,我會在警衛本身中獲得我期望的用戶上下文。 不要在模塊中注冊 RoleGuard 會導致它首先注冊並首先觸發。
*.module.ts
imports: [],
providers: [{provide: APP_GUARD, useClass: RolesGuard} ,], // remove guard
controllers: [],
exports: [],
讓您的 RolesGuard 擴展 AuthGuard('StrategyName') 然后調用 super.canActivate 例如:
@Injectable()
export class RolesGuard extends AuthGuard('jwt') {
async canActivate(context: ExecutionContext): Promise<boolean> {
// call AuthGuard in order to ensure user is injected in request
const baseGuardResult = await super.canActivate(context);
if(!baseGuardResult){
// unsuccessful authentication return false
return false;
}
// successfull authentication, user is injected
const {user} = context.switchToHttp().getRequest();
}
}
換句話說,您必須先進行身份驗證,然后再進行授權
如果其他人偶然發現了這個問題:將多個守衛放入一個@UseGuards
裝飾器可以工作,但是如果您想將它們分開(例如,如果您使用自定義裝飾器),您可以通過放置讓第二個守衛訪問req.user
它在將用戶置於請求對象上的@UseGuards
調用之前,如下例所示:
@RestrictTo(UserAuthorities.admin)
@UseGuards(JwtAuthGuard)
@Get("/your-route")
這似乎是裝飾器在 TypeScript 中工作方式的結果。
您還可以使用多個角色進行基於角色的身份驗證。
在用戶解析器中
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { RolesGuard } from 'src/guards/auth.guard';
@UseGuards(new RolesGuard(['admin']))
@Resolver()
export class UserResolver { ... }
在角色衛士中
import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class RolesGuard extends AuthGuard('jwt') {
constructor(private roles: string[] | null) {
super();
}
canActivate(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const { req } = ctx.getContext();
return super.canActivate(new ExecutionContextHost([req]));
}
handleRequest(err: any, user: any, info: string) {
if (!this.roles) {
return user || null;
}
if (!user) {
throw new UnauthorizedException('Not Valid User.');
}
const role = user.role;
const doesRoleMatch = this.roles.some(r => r === role);
if (!doesRoleMatch) {
throw new UnauthorizedException('Not Valid User.');
}
return user;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.