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

如何使用Morgan记录Next.js中Next-Auth认证用户信息?

在Next.js/React中结合next-auth与morgan记录认证用户信息

为什么:remote-user无法获取用户信息

:remote-user是morgan针对HTTP基本认证设计的令牌,而next-auth使用Session或JWT认证机制,和HTTP基本认证不兼容,因此无法通过该令牌获取用户信息。

解决方案:自定义请求头 + morgan自定义令牌

方法一:客户端添加请求头,服务器端通过morgan捕获

1. 客户端请求时携带用户信息到请求头

在发送API请求前,通过next-auth的getSession或useSession钩子获取当前用户会话,将非敏感的用户信息(如ID、用户名)添加到请求头中:

import { getSession } from 'next-auth/react';

async function fetchProtectedData() {
  const session = await getSession();
  const response = await fetch('/api/protected-endpoint', {
    method: 'GET',
    headers: {
      // 自定义请求头,建议用X-前缀区分自定义头
      'X-User-ID': session?.user?.id || 'anonymous',
      'X-Username': session?.user?.name || 'anonymous'
    }
  });
  const data = await response.json();
  // 处理返回数据
}

2. 服务器端配置morgan捕获请求头信息

根据你使用的Next.js路由模式,选择对应的配置方式:

情况1:使用Next.js Middleware(Pages/App Router通用)

创建middleware.js(或middleware.ts)文件,配置morgan自定义令牌并应用到指定路由:

import morgan from 'morgan';
import { NextResponse } from 'next/server';

// 定义morgan自定义令牌,从请求头中提取用户信息
morgan.token('user-id', (req) => req.headers.get('x-user-id') || 'anonymous');
morgan.token('username', (req) => req.headers.get('x-username') || 'anonymous');

// 自定义日志格式
const morganLogger = morgan(':method :url :status :response-time ms - UserID: :user-id | Username: :username');

export function middleware(request) {
  // 执行morgan日志记录
  morganLogger(request, {}, () => {});
  return NextResponse.next();
}

// 指定需要应用日志中间件的路由(比如所有API路由)
export const config = {
  matcher: ['/api/:path*'],
};
情况2:使用自定义Express服务器

如果你的项目使用自定义Express服务器,可直接集成morgan并结合next-auth获取会话:

const express = require('express');
const next = require('next');
const morgan = require('morgan');
const { getServerSession } = require('next-auth/next');
const { authOptions } = require('./pages/api/auth/[...nextauth]');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  // 先通过next-auth获取服务器端会话,挂载到req对象
  server.use(async (req, res, next) => {
    const session = await getServerSession(req, res, authOptions);
    req.authUser = session?.user;
    next();
  });

  // 基于服务器端会话定义morgan令牌
  morgan.token('auth-user-id', (req) => req.authUser?.id || 'anonymous');
  morgan.token('auth-username', (req) => req.authUser?.name || 'anonymous');

  // 配置morgan日志格式
  server.use(morgan(':method :url :status :response-time ms - UserID: :auth-user-id | Username: :auth-username'));

  // 处理所有Next.js路由
  server.all('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(3000, (err) => {
    if (err) throw err;
    console.log('> Ready on http://localhost:3000');
  });
});

方法二:直接在服务器端通过next-auth获取会话(更安全)

这种方式不需要客户端传递请求头,直接在服务器端通过getServerSession获取用户会话,避免客户端篡改请求头的风险,适合敏感场景。代码示例可参考上面自定义Express服务器中的中间件部分,或在单个API路由中实现:

// pages/api/protected-endpoint.js
import { getServerSession } from 'next-auth/next';
import { authOptions } from './auth/[...nextauth]';
import morgan from 'morgan';

// 初始化morgan并自定义令牌
morgan.token('user-id', (req) => req.authUser?.id || 'anonymous');
const logger = morgan(':method :url :status - UserID: :user-id');

export default async function handler(req, res) {
  // 获取服务器端会话
  const session = await getServerSession(req, res, authOptions);
  req.authUser = session?.user;

  // 执行日志记录
  logger(req, res, () => {});

  // 处理API逻辑
  res.status(200).json({ data: 'Protected content', user: req.authUser });
}

注意事项

  • 不要在请求头中传递敏感信息(如密码、邮箱),只传递用户ID、用户名等非敏感标识。
  • Next.js Middleware中的request是Web Request对象,需用headers.get()获取头信息;Express环境下直接通过req.headers['header-name']访问。
  • 若使用App Router,确保middleware.js放在项目根目录或app目录下。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:05:05