我下载了19-auth示例并向其添加了一些console.log调试代码,然后发现了一些问题。
JwtAuthGuard中的代码永远不会执行:'2222222'未在下面的代码中打印到控制台:
canActivate(context: ExecutionContext) {
console.log('22222222222');
// add your custom authentication logic here
// for example, call super.logIn(request) to establish a session.
return super.canActivate(context);
}
当我在AuthController中将防护改为JwtAuthGuard时:
@get('data')
@UseGuards(JwtAuthGuard)
findAll(@Req() req) {
return req.user;
// this route is restricted by AuthGuard
// JWT strategy
}
调用了JwtAuthGuard中的代码,但在canActivate函数中,我无法从请求中获取用户信息。并且在JwtStrategy之前调用了canActivate函数?
有人可以解释auth模块的代码执行方式,以及如何在JwtAuth Guard中获取用户信息吗?
在此处粘贴最新代码和控制台日志:
JwtStrategy
/**
* jwt passport 调用validate方法来判断是否授权用户进行接口调用
* @param payload
*/
async validate(payload: AuthPayload) {
Logger.log(`payload is ${JSON.stringify(payload)}`, 'JwtStrategy');
const user = await this.authService.validateUser(payload.id);
if (!user) {
throw new UnauthorizedException('不存在的用户信息');
}
return user;
}
JwtAuthGuard
canActivate(context: ExecutionContext) {
// add your custom authentication logic here
// for example, call super.logIn(request) to establish a session.
// this.accessPriv = this.reflector.get<string>('accessPriv', context.getHandler());
console.log('canActivate executed 111111111111111111');
return super.canActivate(context);
}
和控制台日志如下:
canActivate executed 111111111111111111
[Nest] 14080 - 2019-04-01 11:19 [JwtStrategy] payload is {"userName":"fanliang","id":"1","iat":1553772641,"exp":1554377441} +2286ms
it seems that the canActivate() function of JwtAuthGuard executed before the validate() function of JwtStrategy, but the user info was attached to the request after JwtStrategy validate().
我想要的是在自定义AuthGuard的canActivate()中获取请求中的用户信息,例如JwtAuthGuard
我有一个适合我的解决方案。在我自己的逻辑之前调用super.canActivate。 似乎是由它触发的req.user的人口。 一个例子:
import { ExecutionContext, Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { Request } from "express";
@Injectable()
export class AuthGuardWithAllowSentry extends AuthGuard("jwt") {
public async canActivate(context: ExecutionContext) {
// that code will call the passport jwt
const origCanActivate = await super.canActivate(context);
// now we have request.user!
const http = context.switchToHttp();
const request = http.getRequest<Request>();
console.log(request.user)
if (request.header("X-Sentry-Token") === "blablabla") {
if (request.method === "GET" && request.path.endsWith(".map")) {
return true;
}
}
// some random logic
return request.user.roles.includes("admin")
}
}
对我来说,感觉更像是一种解决方法,而不是一种真实的东西。
我同意19-auth
样本有点令人困惑。这主要是因为它包括JWTAuthGuard
(作为建立自定义守卫的参考)但它从未实际使用过。相反,原始使用普通AuthGuard
已经设置为提供JWT功能。然而,两名警卫都利用了JWTStrategy
。如果你想更好地理解这一点,你可以尝试更新你的AuthController
:
@Get('data')
@UseGuards(AuthGuard())
findAll() {
// this route is restricted by AuthGuard
// JWT strategy
return {
message: 'Successfully passed AuthGuard',
};
}
@Get('custom-jwt')
@UseGuards(new JwtAuthGuard())
// this route is restricted by JWTAuthGuard custom
// JWT strategy
customJwt() {
return {
message: 'Successfully passed JWTAuthGuard',
};
}
重要的是,为了通过任何一个保护,您必须发送请求,并将Authorization标头正确设置为从token
端点返回的标记。
例如:Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAZW1haWwuY29tIiwiaWF0IjoxNTU0MDUyNDczLCJleHAiOjE1NTQwNTYwNzN9.3Q8_FC-qFXk1F4KmMrHVSmmNGPAyHdt2myr5c18_E-U
我发现最简单的方法是使用像Postman或Insomnia这样的工具来构建请求和设置Headers等,但你也可以使用CURL。一旦您使用有效令牌设置Authorization
标头,您就可以击中两个受保护的端点。如果你在JWTStrategy中放置一个console.log
,你会看到两个警卫最终都使用validate
方法来正确地检索用户。