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

如何在Next.js全局服务中获取Authorization头中的用户邮箱

解决方案:利用Node.js异步本地存储(AsyncLocalStorage)实现全局用户上下文

针对你的需求,我们可以用Node.js原生的AsyncLocalStorage来在异步调用链中传递用户邮箱上下文,不需要在每个API路由手动传递参数,完美适配你的限制条件。

实现步骤

1. 封装上下文管理工具

创建一个全局的上下文工具类,用来存储和获取请求级别的用户信息:

// src/utils/request-context.ts
import { AsyncLocalStorage } from 'async_hooks';

// 定义上下文结构
type RequestContext = {
  userEmail: string;
};

// 初始化异步本地存储实例
const asyncLocalStorage = new AsyncLocalStorage<RequestContext>();

// 执行回调并注入上下文
export const runWithContext = (context: RequestContext, callback: () => Promise<void>) => {
  return asyncLocalStorage.run(context, callback);
};

// 获取当前上下文
export const getCurrentContext = () => {
  return asyncLocalStorage.getStore();
};

// 快捷获取当前用户邮箱
export const getCurrentUserEmail = () => {
  return getCurrentContext()?.userEmail;
};

2. 编写API路由的上下文注入包装器

写一个高阶函数,统一处理所有API路由的用户邮箱提取和上下文注入逻辑:

// src/middleware/api-context-wrapper.ts
import type { NextApiHandler } from 'next';
import { runWithContext } from '../utils/request-context';

// 从请求头解析用户邮箱(这里复用你middleware中已验证的token解码逻辑)
const extractUserEmail = (req: NextApiRequest): string => {
  const authHeader = req.headers.authorization;
  if (!authHeader) throw new Error('未授权');
  
  const token = authHeader.split(' ')[1];
  // 替换成你实际的token解码逻辑(和middleware保持一致)
  const decodedToken = /* 解码token并获取email的代码 */;
  return decodedToken.email;
};

// 包装API handler,注入用户上下文
export const withUserContext = (handler: NextApiHandler): NextApiHandler => {
  return async (req, res) => {
    try {
      const userEmail = extractUserEmail(req);
      // 注入上下文并执行原handler
      await runWithContext({ userEmail }, async () => {
        await handler(req, res);
      });
    } catch (err) {
      res.status(401).json({ message: '身份验证失败' });
    }
  };
};

3. 修改API路由使用包装器

给你的API路由加上上下文包装:

// pages/api/blogs/index.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { container } from 'tsyringe';
import { ManageBlog } from '../../../src/module/blog/manage-blog';
import { withUserContext } from '../../../src/middleware/api-context-wrapper';

async function handler(req: NextApiRequest, res: NextApiResponse) {
    const manageBlog = container.resolve(ManageBlog);
    switch (req.method) {
        case 'GET':
            const loadedBlog = await manageBlog.readBlog();
            res.status(200).json(loadedBlog);
            break;
        default:
            res.setHeader('Allow', ['GET']);
            res.status(405).end(`Method ${req.method} Not Allowed`);
    }
}

// 用上下文包装器导出handler
export default withUserContext(handler);

4. 在服务类中直接获取用户邮箱

现在你的业务服务可以直接从上下文获取邮箱,无需依赖请求对象:

// src/module/blog/manage-blog.ts
import { autoInjectable } from 'tsyringe';
import { getCurrentUserEmail } from '../../utils/request-context';

@autoInjectable()
export class ManageBlog {
    public async readBlog() {
        const userEmail = getCurrentUserEmail();
        if (!userEmail) {
            throw new Error('无法获取当前用户信息');
        }
        
        // 这里直接使用userEmail做业务逻辑
        console.log('当前操作用户:', userEmail);
        // 你的业务代码...
        return { /* 返回业务数据 */ };
    }
}

方案适配性说明

  • 避开边缘环境限制:上下文注入逻辑运行在Next.js API路由的Node.js环境中,和边缘环境的middleware完全解耦
  • 服务类无需直接访问请求头:通过上下文工具获取邮箱,实现了业务逻辑与请求对象的解耦
  • 无需拦截器:用高阶函数实现统一的上下文注入,相当于轻量级的请求预处理逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 22:32:34