我下载了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模块执行代码,以及如何在JwtAuthGuard中获取用户信息吗?
在此处粘贴最新代码和控制台日志:
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
答案 0 :(得分:0)
我有一个对我有用的解决方案。
在我自己的逻辑之前调用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")
}
}
对我来说,它更像是一种变通方法,而不是真实的东西。
答案 1 :(得分:-1)
我同意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',
};
}
重要的部分是,为了越过任何一个防护措施,您必须发送带有正确设置为token
端点返回的令牌的Authorization标头的请求。
例如:Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAZW1haWwuY29tIiwiaWF0IjoxNTU0MDUyNDczLCJleHAiOjE1NTQwNTYwNzN9.3Q8_FC-qFXk1F4KmMrHVSmmNGPAyHdt2myr5c18_E-U
我发现使用Postman或Insomnia之类的工具来构造请求和设置Header等最简单,但是您也可以使用CURL。为Authorization
标头设置有效令牌后,您将可以同时访问受保护端点的和。如果在JWTStrategy中放入console.log
,您将看到两个保护都最终使用validate
方法来正确地检索用户。