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

如何使用Azure AD Access Token实现React SPA与Node.js后端REST API的授权验证及角色访问控制?

验证Azure AD Access Token & 基于角色授权的完整方案

看起来你已经搞定了前端React的Azure AD Implicit Flow登录,接下来后端Node.js的Token验证和角色授权其实没那么复杂,我给你梳理一套落地性强的方案:

一、先明确安全访问的正确流程

先把前后端的交互逻辑理清楚,这是后续所有验证的基础:

  1. 前端React通过Implicit Flow拿到Azure AD的Access Token(你已经实现这一步了)
  2. 前端每次调用后端API时,把Token放在请求头的Authorization里,格式是 Bearer <你的Access Token>
  3. 后端收到请求后,先验证Token的有效性,再检查用户角色是否匹配端点的权限要求
  4. 验证通过就返回数据,不通过就返回401(未授权)或403(无权限)

二、后端验证Azure Access Token的有效性

Node.js这边推荐用微软官方的azure-ad-jwt库来做Token验证,轻量且靠谱,步骤如下:

1. 安装依赖

npm install azure-ad-jwt --save

2. 编写Token验证中间件

创建一个authMiddleware.js文件,统一处理所有请求的Token验证:

const azureAdJwt = require('azure-ad-jwt');

const validateToken = async (req, res, next) => {
  // 从请求头提取Token
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ message: '请提供有效的访问令牌' });
  }

  const token = authHeader.split(' ')[1];
  const validationOptions = {
    audience: '<你的API应用的Application ID URI>', // 必须和Azure AD里配置的API标识符一致,比如api://xxx-xxx-xxx
    issuer: 'https://sts.windows.net/{你的Azure AD租户ID}/' // 替换成你的租户ID
  };

  try {
    // 验证Token的签名、过期时间、受众等核心信息
    const decodedToken = await azureAdJwt.verify(token, validationOptions);
    // 把解析后的用户信息挂载到req上,方便后续授权使用
    req.user = decodedToken;
    next(); // 验证通过,继续执行后续路由逻辑
  } catch (err) {
    console.error('Token验证失败:', err);
    return res.status(401).json({ message: '令牌无效或已过期' });
  }
};

module.exports = validateToken;

划重点:audience必须严格匹配你在Azure AD中注册的后端API的Application ID URI,如果和Token里的aud字段不一致,验证直接失败。

三、基于角色的权限控制

Azure AD的Access Token里会包含你给用户分配的角色(前提是你已经在Azure AD里配置了角色并分配给用户),通常存在Token的roles数组里。接下来做角色授权:

1. 编写角色授权中间件

在authMiddleware.js里新增角色校验的逻辑:

// 新增的角色授权中间件,接收需要的角色作为参数
const requireRole = (requiredRole) => {
  return (req, res, next) => {
    const userRoles = req.user.roles || [];
    if (!userRoles.includes(requiredRole)) {
      return res.status(403).json({ message: '你没有访问该接口的权限' });
    }
    next();
  };
};

// 现在导出两个中间件
module.exports = { validateToken, requireRole };

2. 在API路由中使用中间件

比如你的Express路由文件:

const express = require('express');
const { validateToken, requireRole } = require('./authMiddleware');
const router = express.Router();

// 普通用户和管理员都能访问的产品列表接口
router.get('/products', validateToken, (req, res) => {
  res.json({ products: [{ id: 1, name: '测试产品' }] });
});

// 只有Admin角色能访问的订单列表接口
router.get('/orders', validateToken, requireRole('Admin'), (req, res) => {
  res.json({ orders: [{ id: 1, orderNo: 'ORD-2024-001' }] });
});

// 只有Admin能更新产品详情
router.put('/products/:id', validateToken, requireRole('Admin'), (req, res) => {
  const productId = req.params.id;
  // 这里写你的更新逻辑
  res.json({ message: `产品${productId}更新成功` });
});

module.exports = router;

四、几个关键注意事项

  • 角色配置:你得先在Azure AD的后端API应用注册里,手动添加Admin和Normal User这两个角色,然后给用户或组分配对应的角色,这样生成的Token里才会有roles字段。
  • HTTPS必须用:生产环境一定要用HTTPS传输Token,不然Token很容易被劫持,安全性全无。
  • Token过期处理:前端要监听Token的exp字段(过期时间),快过期时用Azure AD的静默刷新机制获取新Token,别让用户频繁登录。
  • 最小权限原则:给用户分配角色时,尽量只给必要的权限,比如普通用户只需要访问产品列表,就别给Admin角色。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:27:32