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

适用于Azure Functions v4/v5的TypeScript JWT中间件方案咨询

在TypeScript Azure Functions中实现应用级JWT认证中间件模式

不用依赖久未更新的第三方包,你可以通过两种原生/轻量方式实现全局JWT认证,完美适配Azure Functions的特性:

方式一:通用Handler封装(兼容性强,支持所有版本)

这种方式把认证逻辑封装成高阶函数,给所有需要认证的函数统一套一层,也能轻松实现全局覆盖。

步骤1:安装依赖

npm install jsonwebtoken @types/jsonwebtoken

步骤2:编写认证中间件

创建src/middlewares/authMiddleware.ts文件:

import { Context, HttpRequest } from "@azure/functions";
import jwt from "jsonwebtoken";

// 从Azure Functions应用配置中读取密钥,禁止硬写在代码里
const JWT_SECRET = process.env.JWT_SECRET || "临时 fallback 密钥";

// 定义带用户信息的请求类型
type AuthenticatedHttpRequest = HttpRequest & { user: { userId: string; email: string } };
type AuthHandler = (context: Context, req: AuthenticatedHttpRequest) => Promise<void>;

// 高阶函数:接收原始handler,返回带认证逻辑的新handler
export const withAuth = (handler: AuthHandler) => {
  return async (context: Context, req: HttpRequest) => {
    try {
      // 提取Authorization头里的Bearer令牌
      const authHeader = req.headers.authorization;
      if (!authHeader || !authHeader.startsWith("Bearer ")) {
        context.res = { status: 401, body: "请提供有效的Bearer认证令牌" };
        return;
      }

      const token = authHeader.split(" ")[1];
      // 验证JWT,可按需添加iss/aud等验证参数
      const decodedUser = jwt.verify(token, JWT_SECRET) as { userId: string; email: string };

      // 把用户信息挂载到req上,供后续业务逻辑使用
      const authenticatedReq = req as AuthenticatedHttpRequest;
      authenticatedReq.user = decodedUser;

      // 执行原始业务handler
      await handler(context, authenticatedReq);
    } catch (err) {
      context.res = { status: 403, body: "令牌无效或已过期" };
    }
  };
};

步骤3:在函数中使用(或全局统一配置)

单个函数使用:

// src/functions/protectedFunction.ts
import { Context, HttpRequest } from "@azure/functions";
import { withAuth } from "../middlewares/authMiddleware";

async function protectedHandler(context: Context, req: HttpRequest & { user: any }) {
  context.res = {
    body: `欢迎回来,${req.user.email}!你的用户ID是${req.user.userId}`,
  };
}

// 导出经过认证封装的函数
export default withAuth(protectedHandler);

如果要全局所有函数统一应用认证,可以通过入口文件批量封装:

// src/index.ts
import { Context, HttpRequest, AzureFunction } from "@azure/functions";
import { withAuth } from "./middlewares/authMiddleware";

// 导入所有业务函数
import protectedFunc1 from "./functions/protectedFunc1";
import protectedFunc2 from "./functions/protectedFunc2";
import publicFunc from "./functions/publicFunc"; // 不需要认证的公开接口

// 映射函数名到处理逻辑,统一封装需要认证的函数
const functionHandlers: Record<string, AzureFunction> = {
  protectedFunc1: withAuth(protectedFunc1),
  protectedFunc2: withAuth(protectedFunc2),
  publicFunc: publicFunc, // 公开接口直接使用原始handler
};

// 统一入口处理请求
export default async function (context: Context, req: HttpRequest) {
  const targetHandler = functionHandlers[context.executionContext.functionName];
  if (!targetHandler) {
    context.res = { status: 404, body: "请求的函数不存在" };
    return;
  }
  await targetHandler(context, req);
}

方式二:官方Middleware机制(Azure Functions v4+)

如果用的是v4及以上版本的Azure Functions,可以用官方提供的Middleware特性,写法更贴近Express中间件,支持全局注册。

步骤1:确保依赖版本

npm install @azure/functions@latest

步骤2:编写认证中间件

// src/middlewares/authMiddleware.ts
import { Middleware, Context, HttpRequest } from "@azure/functions";
import jwt from "jsonwebtoken";

const JWT_SECRET = process.env.JWT_SECRET || "临时 fallback 密钥";

export const authMiddleware: Middleware = async (context, req, next) => {
  try {
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith("Bearer ")) {
      context.res = { status: 401, body: "请提供有效的Bearer认证令牌" };
      return;
    }

    const token = authHeader.split(" ")[1];
    const decodedUser = jwt.verify(token, JWT_SECRET) as { userId: string; email: string };
    (req as any).user = decodedUser;

    // 执行下一个中间件或业务handler
    await next();
  } catch (err) {
    context.res = { status: 403, body: "令牌无效或已过期" };
  }
};

步骤3:全局注册中间件并配置函数

// src/index.ts
import { app } from "@azure/functions";
import { authMiddleware } from "./middlewares/authMiddleware";

// 注册全局中间件,所有HTTP函数都会先执行认证逻辑
app.use(authMiddleware);

// 注册需要认证的函数
app.http("protectedFunc", {
  methods: ["GET"],
  authLevel: "anonymous", // 这里设为匿名,因为我们自己处理认证
  handler: async (context, req) => {
    return {
      body: `欢迎回来,${(req as any).user.email}!你的用户ID是${(req as any).user.userId}`,
    };
  },
});

// 注册不需要认证的公开函数
app.http("publicFunc", {
  methods: ["GET"],
  authLevel: "anonymous",
  handler: async () => {
    return { body: "这是公开访问的接口" };
  },
});

一些最佳实践

  • 密钥管理:JWT密钥一定要存在Azure Functions的应用配置(Configuration)里,绝对不能硬编码
  • 细化错误处理:可以根据jsonwebtoken抛出的错误类型,返回更具体的提示(比如令牌过期、签名无效等)
  • 权限扩展:如果需要细粒度权限控制,可以在JWT的payload里加入角色信息,在中间件中验证角色
  • 排除特定函数:全局认证时,可以通过context.executionContext.functionName判断,跳过不需要认证的函数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:00:54