Vue3集成Keycloak时对象属性刷新页面后返回undefined问题求解
问题原因分析
- 核心错误1:
main.ts中重复创建了Vue应用实例,Keycloak插件配置实际未生效
你先创建了一个应用实例配置了Keycloak插件,随后又重新创建了另一个全新的实例挂载路由、仓库并挂载到DOM,两个实例完全独立,前面的Keycloak配置根本没有作用到实际运行的应用上。 - 错误2:Keycloak初始化是异步流程,未等待初始化完成就同步读取属性
页面刷新时Keycloak还在执行初始化登录逻辑,此时同步读取token自然是undefined。你直接打印keycloak对象能看到完整内容是浏览器控制台的特性:控制台输出的是对象的引用,你点开对象查看属性时初始化已经完成,浏览器会读取对象最新的属性值,不代表打印的那一刻token已经存在。
解决方案
第一步:修复main.ts的实例重复问题
将所有插件都挂载到同一个应用实例上,修改后的main.ts代码如下:
import { vueKeycloak } from "@baloise/vue-keycloak"; import { createApp } from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; const app = createApp(App); app.use(vueKeycloak, { initOptions: { onLoad: "login-required", // default }, config: { url: "https://xxxxxxxxxxxxxx.com/auth/", realm: "xxxxx", clientId: "xxxxclient", }, }); // 同一个实例挂载所有插件后再挂载到DOM app.use(store).use(router).mount("#app");
第二步:正确读取Keycloak属性
@baloise/vue-keycloak提供了响应式的初始化状态和属性,推荐两种读取方式:
方式1:监听初始化完成状态后读取
import { defineComponent, watch } from "vue"; import { useKeycloak } from "@baloise/vue-keycloak"; export default defineComponent({ name: "Home", setup() { const { keycloak, isReady } = useKeycloak(); // 监听初始化完成状态,确认初始化后再读取属性 watch(isReady, (ready) => { if (ready) { console.log("token值:", keycloak.token); console.log("用户解析信息:", keycloak.idTokenParsed); } }) return {}; }, });
方式2:直接使用封装好的响应式属性
@baloise/vue-keycloak已经把常用属性封装成了响应式变量,可以直接调用:
import { defineComponent, watch } from "vue"; import { useKeycloak } from "@baloise/vue-keycloak"; export default defineComponent({ name: "Home", setup() { const { token, isAuthenticated, userProfile } = useKeycloak(); // 直接监听token变化即可获取最新值 watch(token, (newToken) => { if (newToken) { // 可在这里执行请求头赋值等逻辑 console.log("获取到有效token:", newToken); } }) return {}; }, });
注意:不要在模板中直接调用函数读取Keycloak属性,模板渲染时机早于Keycloak初始化完成时机,会取不到值。
内容的提问来源于stack exchange,提问作者DnD2k21
相关产品推荐
相关产品推荐

