JsonWebTokenError: jwt must be provided nest JS
JsonWebTokenError: jwt must be provided nest JS
我正在尝试使用 nest.JS 从我的本地后端传递一些数据,登录成功并且 jwt 令牌显示在 cookie 中,但错误显示:
[Nest] 39 - 02/22/2022, 9:50:59 AM ERROR [ExceptionsHandler] jwt must be provided
nest-admin-backend-1 | JsonWebTokenError: jwt must be provided
nest-admin-backend-1 | at Object.module.exports [as verify] (/app/node_modules/jsonwebtoken/verify.js:53:17)
nest-admin-backend-1 | at /app/node_modules/@nestjs/jwt/dist/jwt.service.js:42:53
nest-admin-backend-1 | at new Promise (<anonymous>)
nest-admin-backend-1 | at JwtService.verifyAsync (/app/node_modules/@nestjs/jwt/dist/jwt.service.js:42:16)
nest-admin-backend-1 | at AuthService.userId (/app/src/auth/auth.service.ts:16:44)
nest-admin-backend-1 | at AuthController.user (/app/src/auth/auth.controller.ts:68:43)
nest-admin-backend-1 | at /app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
nest-admin-backend-1 | at processTicksAndRejections (node:internal/process/task_queues:93:5
至于代码,没有任何错误,我正在按照教程进行操作,但它不起作用。
如果我按照错误消息进行操作,它会在我的 auth.service 和 auth.controller 文件中说明错误,所以这是我的文件片段:
Auth.controller
export class AuthController {
constructor(
private userService: UserService,
private jwtService: JwtService,
private authService: AuthService,
) {
}
@Post('register')
async register(@Body() body: RegisterDto) {
if (body.password !== body.password_confirm) {
throw new BadRequestException('Password do not match!');
}
const hashed = await bcrypt.hash(body.password, 12);
{ }
return this.userService.create({
firstName: body.firstName,
lastName: body.lastName,
email: body.email,
password: hashed,
role: { id: 1 }
});
}
@Post('login')
async login(
@Body('email') email: string,
@Body('password') password: string,
@Res({ passthrough: true }) response: Response,
) {
const user = await this.userService.findOne({ email });
if (!user) {
throw new NotFoundException('User not found!');
}
if (!await bcrypt.compare(password, (await user).password)) {
throw new BadRequestException('Invalid password!');
}
// Generate JWT
const jwt = await this.jwtService.signAsync({ id: user.id })
response.cookie('jwt', jwt, { httpOnly: true });
return user;
}
@UseGuards(AuthGuard) // This is a custom guard
// Authenticate user and generate JWT
@Get('user')
async user(@Req() request: Request) {
const id = await this.authService.userId(request);
// Get user from the database
return this.userService.findOne({ id });
}
@UseGuards(AuthGuard) // Check if user is authenticated
@Post('logout')
async logout(@Res({ passthrough: true }) response: Response) {
response.clearCookie('jwt');
return {
message: 'Logged out successfully',
}
}
}
Auth.service
export class AuthService {
constructor(private jwtService: JwtService) {
}
async userId(request: Request): Promise<number> {
const cookie = request['jwt'];
// Get data from the Cookie
const data = await this.jwtService.verifyAsync(cookie);
// Get user from the database
return data['id'];
}
}
即使我已经登录,我也无法访问邮递员的 localhost:8000/api/user。知道如何解决吗?
Cookie 是 HTTP 服务器和浏览器之间的协议,因此 Postman 和后端不能只登录并发送 cookie header。
要允许您的 API 服务器识别应用程序(移动、桌面和服务器),需要引入一种额外的方式来发送 JWT。
除了 Cookies
之外,还允许将 JWT 作为 HTTP header 发送。使用 Authorization
header 作为发送 JWT 的辅助方法。
要做到这一点,您需要:
- 将您的
/login
修改为 return JWT 作为纯文本(而不是用户)
@Post('login')
async login(
@Body('email') email: string,
@Body('password') password: string,
@Res({ passthrough: true }) response: Response,
) {
const user = await this.userService.findOne({ email });
...
// Generate JWT
const jwt = await this.jwtService.signAsync({ id: user.id })
response.cookie('jwt', jwt, { httpOnly: true }); // <-- for browsers
return jwt; // <--- for applications
}
现在应用程序有责任根据子序列请求存储和发送 JWT(使用 Authorization
header)
- 更新您的
AuthGuard
以检查 cookie
和 Authorization
header 中的 JWT。
我正在尝试使用 nest.JS 从我的本地后端传递一些数据,登录成功并且 jwt 令牌显示在 cookie 中,但错误显示:
[Nest] 39 - 02/22/2022, 9:50:59 AM ERROR [ExceptionsHandler] jwt must be provided
nest-admin-backend-1 | JsonWebTokenError: jwt must be provided
nest-admin-backend-1 | at Object.module.exports [as verify] (/app/node_modules/jsonwebtoken/verify.js:53:17)
nest-admin-backend-1 | at /app/node_modules/@nestjs/jwt/dist/jwt.service.js:42:53
nest-admin-backend-1 | at new Promise (<anonymous>)
nest-admin-backend-1 | at JwtService.verifyAsync (/app/node_modules/@nestjs/jwt/dist/jwt.service.js:42:16)
nest-admin-backend-1 | at AuthService.userId (/app/src/auth/auth.service.ts:16:44)
nest-admin-backend-1 | at AuthController.user (/app/src/auth/auth.controller.ts:68:43)
nest-admin-backend-1 | at /app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
nest-admin-backend-1 | at processTicksAndRejections (node:internal/process/task_queues:93:5
至于代码,没有任何错误,我正在按照教程进行操作,但它不起作用。
如果我按照错误消息进行操作,它会在我的 auth.service 和 auth.controller 文件中说明错误,所以这是我的文件片段:
Auth.controller
export class AuthController {
constructor(
private userService: UserService,
private jwtService: JwtService,
private authService: AuthService,
) {
}
@Post('register')
async register(@Body() body: RegisterDto) {
if (body.password !== body.password_confirm) {
throw new BadRequestException('Password do not match!');
}
const hashed = await bcrypt.hash(body.password, 12);
{ }
return this.userService.create({
firstName: body.firstName,
lastName: body.lastName,
email: body.email,
password: hashed,
role: { id: 1 }
});
}
@Post('login')
async login(
@Body('email') email: string,
@Body('password') password: string,
@Res({ passthrough: true }) response: Response,
) {
const user = await this.userService.findOne({ email });
if (!user) {
throw new NotFoundException('User not found!');
}
if (!await bcrypt.compare(password, (await user).password)) {
throw new BadRequestException('Invalid password!');
}
// Generate JWT
const jwt = await this.jwtService.signAsync({ id: user.id })
response.cookie('jwt', jwt, { httpOnly: true });
return user;
}
@UseGuards(AuthGuard) // This is a custom guard
// Authenticate user and generate JWT
@Get('user')
async user(@Req() request: Request) {
const id = await this.authService.userId(request);
// Get user from the database
return this.userService.findOne({ id });
}
@UseGuards(AuthGuard) // Check if user is authenticated
@Post('logout')
async logout(@Res({ passthrough: true }) response: Response) {
response.clearCookie('jwt');
return {
message: 'Logged out successfully',
}
}
}
Auth.service
export class AuthService {
constructor(private jwtService: JwtService) {
}
async userId(request: Request): Promise<number> {
const cookie = request['jwt'];
// Get data from the Cookie
const data = await this.jwtService.verifyAsync(cookie);
// Get user from the database
return data['id'];
}
}
即使我已经登录,我也无法访问邮递员的 localhost:8000/api/user。知道如何解决吗?
Cookie 是 HTTP 服务器和浏览器之间的协议,因此 Postman 和后端不能只登录并发送 cookie header。
要允许您的 API 服务器识别应用程序(移动、桌面和服务器),需要引入一种额外的方式来发送 JWT。
除了 Cookies
之外,还允许将 JWT 作为 HTTP header 发送。使用 Authorization
header 作为发送 JWT 的辅助方法。
要做到这一点,您需要:
- 将您的
/login
修改为 return JWT 作为纯文本(而不是用户)
@Post('login')
async login(
@Body('email') email: string,
@Body('password') password: string,
@Res({ passthrough: true }) response: Response,
) {
const user = await this.userService.findOne({ email });
...
// Generate JWT
const jwt = await this.jwtService.signAsync({ id: user.id })
response.cookie('jwt', jwt, { httpOnly: true }); // <-- for browsers
return jwt; // <--- for applications
}
现在应用程序有责任根据子序列请求存储和发送 JWT(使用 Authorization
header)
- 更新您的
AuthGuard
以检查cookie
和Authorization
header 中的 JWT。