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

如何在Node.js Express API中验证React SPA从Keycloak获取的访问令牌

Express后端校验Keycloak访问令牌的缺失步骤整理

1. 安装对应依赖

你可以选择Keycloak官方适配的中间件,或者通用JWT校验库,对应安装命令如下:

  • 官方keycloak-connect方案:npm install keycloak-connect
  • 通用JWT手动校验方案:npm install jsonwebtoken

2. 准备Keycloak校验必要配置

你需要提前从Keycloak控制台获取以下信息,用于后续校验:

  • 所属Realm的RS256公钥(获取路径:Realm设置→密钥→选中RS256算法对应的公钥)
  • Realm的issuer地址,格式为https://<你的Keycloak域名>/realms/<你的Realm名称>
  • 对应客户端的ID(即前端申请令牌时使用的client_id)
  • 若使用官方中间件,可直接下载keycloak.json配置文件放到后端项目根目录,需把配置中的bearer-only属性设为true,适配后端API无登录页的无状态场景

3. 前端请求适配

需确保前端发起API请求时,将获取到的访问令牌放在Authorization请求头中,格式为:

Authorization: Bearer <你拿到的access_token字符串>

如果配置了跨域,需要在Express的CORS配置中允许Authorization请求头,避免被浏览器拦截。

4. 后端实现校验逻辑

方案A:使用官方keycloak-connect中间件(推荐)

初始化中间件并挂载到需要保护的路由即可,示例代码:

const Keycloak = require('keycloak-connect');
const express = require('express');
const app = express();

// 无状态API可以不传session配置直接初始化
const keycloak = new Keycloak({});
app.use(keycloak.middleware());

// 受保护的路由添加keycloak.protect()中间件即可自动校验令牌
app.get('/api/protected/data', keycloak.protect(), (req, res) => {
  // 校验通过后可从req.kauth.grant中获取用户信息
  res.json({ data: '敏感数据', user: req.kauth.grant.access_token.content });
});

方案B:手动实现JWT校验逻辑

如果不想引入完整的Keycloak中间件,可以自己实现校验中间件,示例代码:

const jwt = require('jsonwebtoken');
const express = require('express');
const app = express();

// 替换为你自己的Keycloak配置
const KEYCLOAK_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
你从控制台复制的公钥内容
-----END PUBLIC KEY-----`;
const KEYCLOAK_ISSUER = 'https://你的Keycloak域名/realms/你的Realm名称';
const CLIENT_ID = '你的客户端ID';

// 自定义校验中间件
const validateKeycloakToken = (req, res, next) => {
  const authHeader = req.headers.authorization;
  // 校验请求头是否携带符合格式的令牌
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: '缺少有效访问令牌' });
  }
  const token = authHeader.split(' ')[1];
  try {
    // 校验签名、有效期、发行方、受众
    const decodedToken = jwt.verify(token, KEYCLOAK_PUBLIC_KEY, {
      issuer: KEYCLOAK_ISSUER,
      audience: CLIENT_ID
    });
    // 挂载用户信息到请求对象,供后续路由使用
    req.user = decodedToken;
    next();
  } catch (error) {
    return res.status(401).json({ error: '令牌无效或已过期' });
  }
};

// 受保护路由使用自定义中间件
app.get('/api/protected/data', validateKeycloakToken, (req, res) => {
  res.json({ data: '敏感数据', user: req.user });
});

常见遗漏点排查

  • 未将后端客户端的访问类型设置为bearer-only,导致校验逻辑异常
  • 公钥配置时漏加-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----包裹,导致签名校验失败
  • 未处理令牌过期场景,需要返回401状态码触发前端重新申请令牌
  • 校验逻辑漏校验issuer、audience字段,存在安全风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:54:02