You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nest.js与Next.js服务端Token处理及Session类工具咨询

Nest.js服务端Token处理及Next.js服务端组件Token管理方案

一、Nest.js侧的Token处理

1. 生成Token(以JWT为例)

Nest.js常用@nestjs/jwt包生成JWT令牌,用户登录验证通过后,签发包含用户核心信息的Token:

// auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(private jwtService: JwtService) {}

  async login(user: any) {
    const payload = { username: user.username, sub: user.id };
    return {
      access_token: this.jwtService.sign(payload, { expiresIn: '15m' }), // 短时效访问令牌
      refresh_token: this.jwtService.sign(payload, { expiresIn: '7d' }) // 长时效刷新令牌
    };
  }
}

需要在模块里配置JWT密钥和默认选项(密钥别硬编码,从环境变量读取):

// auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';

@Module({
  imports: [
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: '15m' },
    }),
  ],
  providers: [AuthService],
  exports: [AuthService],
})
export class AuthModule {}

2. 验证Token

用Passport的JWT守卫拦截未携带有效Token的请求,保护需要授权的接口:

// jwt-auth.guard.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

配置JWT策略,解析并验证Token的合法性:

// jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // 从请求头Authorization字段提取Token
      ignoreExpiration: false,
      secretOrKey: process.env.JWT_SECRET,
    });
  }

  async validate(payload: any) {
    // 验证通过后,用户信息会挂载到req.user上供接口使用
    return { userId: payload.sub, username: payload.username };
  }
}

在需要授权的接口上直接使用守卫:

// user.controller.ts
import { Controller, Get, UseGuards, Request } from '@nestjs/common';
import { JwtAuthGuard } from './jwt-auth.guard';

@Controller('users')
export class UserController {
  @Get('profile')
  @UseGuards(JwtAuthGuard)
  getProfile(@Request() req) {
    return req.user;
  }
}

二、Next.js服务端组件的Token管理

针对你提到的服务端组件(export default async function Test() {})调用API的场景,没法用浏览器Cookie、也无类似PHP Session的工具,这里给你几种实用方案:

1. 单次请求内直接使用

如果只是当前组件调用API需要Token,直接获取后携带在请求头即可,无需持久化:

// app/test/page.tsx
import axios from 'axios';

export default async function Test() {
  // 先调用登录接口获取Token
  const loginRes = await axios.post('http://你的NestAPI地址/auth/login', {
    username: '你的用户名',
    password: '你的密码'
  });
  const { access_token } = loginRes.data;

  // 携带Token调用需要授权的接口
  const profileRes = await axios.get('http://你的NestAPI地址/users/profile', {
    headers: {
      Authorization: `Bearer ${access_token}`
    }
  });

  return <div>用户信息:{JSON.stringify(profileRes.data)}</div>;
}

这种方式简单直接,Token仅在当前服务端请求周期内有效,用完即弃,适合一次性服务端请求场景。

2. 跨请求持久化存储(基于Redis)

如果需要在多个服务端请求之间共享Token,比如用户多次访问不同页面的服务端组件都要用到Token,可以用Redis存储:

// app/test/page.tsx
import axios from 'axios';
import Redis from 'ioredis';

// 初始化Redis连接(建议抽成单独工具文件复用)
const redis = new Redis({
  host: process.env.REDIS_HOST,
  port: parseInt(process.env.REDIS_PORT || '6379'),
});

export default async function Test({ params }: { params: { userId: string } }) {
  // 从Redis读取对应用户的Token
  let access_token = await redis.get(`user:${params.userId}:token`);

  if (!access_token) {
    // 未取到Token则重新登录获取
    const loginRes = await axios.post('http://你的NestAPI地址/auth/login', {
      username: '你的用户名',
      password: '你的密码'
    });
    access_token = loginRes.data.access_token;
    // 将Token存入Redis,过期时间和Token有效期保持一致(比如15分钟)
    await redis.set(`user:${params.userId}:token`, access_token, 'EX', 900);
  }

  // 携带Token调用接口
  const profileRes = await axios.get('http://你的NestAPI地址/users/profile', {
    headers: { Authorization: `Bearer ${access_token}` }
  });

  return <div>用户信息:{JSON.stringify(profileRes.data)}</div>;
}

这种方式能实现跨请求的Token共享,适合需要维持用户登录状态的服务端场景。

3. 自动处理Token过期

Token过期后服务端会返回401错误,此时可以调用刷新Token接口获取新Token,再自动重试请求:

// app/test/page.tsx
import axios from 'axios';

// 封装带Token自动刷新的请求函数
async function fetchWithRefresh(url: string, token: string, refreshToken: string) {
  try {
    return await axios.get(url, {
      headers: { Authorization: `Bearer ${token}` }
    });
  } catch (error: any) {
    if (error.response?.status === 401) {
      // 调用刷新Token接口
      const refreshRes = await axios.post('http://你的NestAPI地址/auth/refresh', {
        refresh_token: refreshToken
      });
      const newToken = refreshRes.data.access_token;
      // 重试原请求
      return await axios.get(url, {
        headers: { Authorization: `Bearer ${newToken}` }
      });
    }
    throw error;
  }
}

export default async function Test() {
  const loginRes = await axios.post('http://你的NestAPI地址/auth/login', {
    username: '你的用户名',
    password: '你的密码'
  });
  const { access_token, refresh_token } = loginRes.data;

  // 调用带自动刷新的请求
  const profileRes = await fetchWithRefresh(
    'http://你的NestAPI地址/users/profile',
    access_token,
    refresh_token
  );

  return <div>用户信息:{JSON.stringify(profileRes.data)}</div>;
}

内容的提问来源于stack exchange,提问作者Kenzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:34:57