如何在NestJS中设置仅HTTP cookie

问题描述 投票:0回答:3

我正在尝试使用accessToken和refreshToken实现JWT授权。 accessToken 和刷新令牌都需要在 HTTP only cookie 中设置。

我尝试了这段代码,但它没有设置cookie。我在这里使用 NestJS 框架。

import { Controller, Request, Post, Body, Response } from '@nestjs/common';
@Controller()
export class UserController {
  constructor() {}

  @Post('users/login')
  async login(
    @Request() req,
    @Body() credentials: { username: string; password: string },
    @Response() res,
  ) {
    try {
      // Login with username and password
      const accessToken = 'something';
      const refreshToken = 'something';
      const user = { username: credentials.username };

      res.cookie('accessToken', accessToken, {
        expires: new Date(new Date().getTime() + 30 * 1000),
        sameSite: 'strict',
        httpOnly: true,
      });
      return res.send(user);
    } catch (error) {
      throw error;
    }
  }
}

res.send() 方法工作正常,我正在获取响应数据。我如何在这里设置 cookie?

这是我的 main.ts 文件:-

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';
import { AuthenticatedSocketIoAdapter } from './chat/authchat.adapter';
import * as cookieParser from 'cookie-parser';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  app.use(cookieParser());
  app.useWebSocketAdapter(new AuthenticatedSocketIoAdapter(app));
  await app.listen(3000);
  Logger.log('User microservice running');
}
bootstrap();

并获取我正在使用的 cookie:-

request.cookies
typescript express cookies jwt nestjs
3个回答
11
投票

评论里的对话:

Axios 在客户端需要将

withCredentials
设置为
true
才能将 cookie 发送回服务器。服务器正在按预期发送和设置 cookie。


6
投票

我遇到了和你几乎一样的问题。 Axios 无法保存 cookie。 Chrome 需要设置 SameSite: 'none', secure: true。 你还是没有工作。它确实使用 fetch 方法保存了 cookie,但仅限于运行 Chromium 的浏览器......所以 mozilla 没有收到它。我的 axios 是:

const response = await axios.post(url+'/login', loginState, {withCredentials: true});

后端Nestjs:Main.ts:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('v1/api');
  app.use(cookieParser());
  app.useGlobalPipes(new ValidationPipe());
  app.enableCors({
    credentials: true,
    origin: process.env.FRONTEND_URL,
  })
  await app.listen(3000);
}

我的AuthService登录功能(记住Res中的passthrought: true)

@Post('login')
async login(
        @Body()body: LoginUserDTO,
        @Res({passthrough: true}) response: Response
    ): Promise<any> {
    const user = await this.userService.getOne({where: {"user_email": body.email}});
    if(!user) {
        throw new NotFoundException('User not found')
    }
    if(!await bcrypt.compare(body.password, user.user_password)) {
        throw new BadRequestException('Password incorrect');
    }
    const frontendDomain = this.configService.get<string>('FRONTEND_DOMAIN');
    const jwtToken = await this.jwtService.signAsync({id: user.user_id});
    response.cookie('jwt', jwtToken, {httpOnly: true, domain: frontendDomain,});

    return {'jwt': jwtToken}
}

奇怪的是,解决我的问题的方法是将域添加到response.cookie中。

还有我的用于 CORS 和 cookie 域的开发环境变量:

FRONTEND_URL = http://localhost:3333
FRONTEND_DOMAIN = localhost

希望我的代码能有所帮助


0
投票

如果您正在寻找设置仅 http cookie 的方法,您可以使用以下取决于引擎(fastify、express)的方法,它会起作用:

async refresh(@Res({ passthrough: true }) res: FastifyReply): Promise<void> {
    const [cookieName, cookieTok] = ['refreshToken', 'someSecretToken'];
    
    // 1. with special method (depends on engine)
    res.setCookie('refresh', 'some_token', { httpOnly: true, maxAge: Date.now() + 60_000 });

    // 2. common way
    res.header('Set-Cookie', [`${cookieName}=${cookieToken};Max-Age=${expiresIn};Path=/;HttpOnly;Secure=True;SameSite=None;`, 'otherCookieAndParams...']);
}

查看 MDN docs

也会有所帮助
© www.soinside.com 2019 - 2024. All rights reserved.