Node.js集成Keycloak出现'keycloak-token'属性读取失败报错求解
问题原因及修复方案
1. 重复输出Initializing Keycloak问题
你把express-session的配置参数错误传入了Keycloak构造函数,导致Keycloak实例初始化逻辑异常,每次调用都重复生成新实例。
2. Cannot read property 'keycloak-token' of undefined报错问题
这个错误是因为keycloak-connect依赖express-session存储令牌信息,你没有提前在express上挂载session中间件,导致请求对象req上不存在session属性,Keycloak读取令牌时抛出异常。
3. 路由未生效隐藏问题
你定义了express Router实例但没有挂载到app上,后续即使Keycloak配置正常,访问/user//admin等端点也会返回404。
具体修改代码
第一步:修改keycloak-config.js
将express-session的配置和Keycloak初始化拆分,session相关配置不要传入Keycloak构造函数:
var session = require('express-session'); var Keycloak = require('keycloak-connect'); const chalk = require('chalk'); let keycloak; // 新增导出memoryStore供外层挂载session使用 let memoryStore; var keycloakConfig = { "realm": "Demo-Realm", "bearer-only": true, "auth-server-url": "http://localhost:8080/auth/", "ssl-required": "external", "resource": "node-microservice", "verify-token-audience": true, "use-resource-role-mappings": true, "confidential-port": 0, "realmPublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1SrR985UGLhBlCReW1p9ypcKbQhjHXDqS3DK78ihqGxLiwNWWsG/ilwD54HbxMjcVIl6hLXZbpd85oAr6HCSjRm8D6HGP6AVfva7s6pQcXmNWIeFGhwOSM/k2rjXkVGpCu3Yhg+Fnx03zA/nSlybhyYJrt/EftbjhCVO58WnAhEY8ytBHZQws+I85BzstClm3dSXj9EiWea6pqB7vpYkMy/nGUBgfOFn30Hqa2Pp7Dxkgd7+G/xRN2JDbg09etgZzt9kXVs1X6LbwAWG60qeNF2ZMCHTZeiHi0FRM7d7irRrc68orrFiEg2Gp7u3urr2ss4JOwSWe9QK/l3eZ3XS6QIDAQAB" }; function initKeycloak() { if(keycloak) { console.log("Returning existing Keycloak instance!"); return keycloak; } else { console.log("Initializing Keycloak..."); memoryStore = new session.MemoryStore(); // Keycloak第一个参数只需要传store即可,session配置放到外层 keycloak = new Keycloak({ store: memoryStore }, keycloakConfig); return keycloak; } } module.exports = { initKeycloak, memoryStore };
第二步:修改index.js
先挂载session中间件,再挂载Keycloak中间件,最后挂载路由:
const express = require('express'); const session = require('express-session'); var router = express.Router(); var app = express(); const keycloakConfig = require('./keycloak-config.js'); const keycloak = keycloakConfig.initKeycloak(); // 先挂载session中间件,必须在keycloak中间件之前 app.use(session({ secret: 'any_key', resave: false, saveUninitialized: true, store: keycloakConfig.memoryStore })); // 再挂载keycloak中间件 app.use(keycloak.middleware()); router.get('/user', keycloak.protect('user'), function (req, res) { res.send("Hello User"); }); router.get('/admin', keycloak.protect('admin'), function (req, res) { res.send("Hello Admin"); }); router.get('/all', keycloak.protect(['user', 'admin']), function (req, res) { res.send("Hello All"); }); app.get('/', function (req, res) { res.send("Server is up!"); }); // 挂载路由到app上 app.use('/', router); app.listen(8081, () => { console.log('服务启动在8081端口'); });
额外校验项
- 确认Keycloak服务正常运行在
http://localhost:8080,Demo-Realm域、node-microservice客户端已正确创建 - 确认
node-microservice客户端的访问类型设置为bearer-only - 如果你使用的是Keycloak 17+版本,默认上下文路径没有
/auth,需要把auth-server-url改为http://localhost:8080/
内容的提问来源于stack exchange,提问作者Leon_Rickert
相关产品推荐
相关产品推荐

