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

Keycloak React Admin UI开发模式启动遇404问题求助

Keycloak Admin UI开发模式启动后访问404问题

我想自定义修改Keycloak的admin-ui,但在开发模式下运行项目时遇到问题:

  1. 先在keycloak-26.4.2/bin目录执行kc.bat start-dev启动Keycloak后端
  2. 进入keycloak-main/js/apps/admin-ui目录运行pnpm run dev,Vite提示服务就绪:
VITE v7.1.10  ready in 2182 ms
  ➜  Local:   http://localhost:5174/
  ➜  Network: http://192.168.61.12:5174/

但直接访问localhost:5174时出现404错误,请求信息:

Request URL http://localhost:5174/
Request Method GET
Status Code 404 Not Found Remote Address [::1]:5174
Referrer Policy strict-origin-when-cross-origin 

环境信息:Keycloak v26.4.2、Node v22.21.0


相关配置文件

admin-ui/package.json

{"name": "@keycloak/keycloak-admin-ui","version": "999.0.0-SNAPSHOT","type": "module","main": "lib/keycloak-admin-ui.js","types": "./lib/keycloak-admin-ui.d.ts","exports": {".": {"import": "./lib/keycloak-admin-ui.js","types": "./lib/keycloak-admin-ui.d.ts"}},"files": ["lib"],"publishConfig": {"access": "public"},"scripts": {"dev": "wireit","build": "wireit","build-lib": "wireit","preview": "wireit","lint": "wireit","test": "wireit","test:integration": "wireit"},"wireit": {"dev": {"command": "vite --host","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"preview": {"command": "vite preview","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"build": {"command": "vite build","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"],"files": ["public","src","tsconfig.json","vite.config.ts"],"output": ["target/classes/theme/keycloak.v2/admin/resources"]},"build-lib": {"command": "cross-env LIB=true vite build","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"lint": {"command": "eslint .","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"test": {"command": "vitest","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"test:integration": {"command": "playwright test","dependencies": ["../../libs/keycloak-admin-client:build"]}},"dependencies": {"@dagrejs/dagre": "^1.1.5","@keycloak/keycloak-admin-client": "workspace:*","@keycloak/keycloak-ui-shared": "workspace:*","@patternfly/patternfly": "^5.4.2","@patternfly/react-core": "^5.4.14","@patternfly/react-icons": "^5.4.2","@patternfly/react-styles": "^5.4.1","@patternfly/react-table": "^5.4.16","@uiw/react-textarea-code-editor": "^3.1.1","admin-ui": "file:","file-saver": "^2.0.5","flat": "^6.0.1","i18next": "^25.6.0","i18next-fetch-backend": "^6.0.0","jszip": "^3.10.1","keycloak-js": "^26.2.0","lodash-es": "^4.17.21","p-debounce": "^5.0.0","react": "^18.3.1","react-dom": "^18.3.1","react-hook-form": "^7.63.0","react-i18next": "^16.0.1","react-router-dom": "^6.30.1","reactflow": "^11.11.4","use-react-router-breadcrumbs": "^4.0.1"},"devDependencies": {"@axe-core/playwright": "^4.10.2","@playwright/test": "^1.56.0","@testing-library/dom": "^10.4.1","@testing-library/jest-dom": "^6.9.1","@testing-library/react": "^16.3.0","@types/dagre": "^0.7.53","@types/file-saver": "^2.0.7","@types/lodash-es": "^4.17.12","@types/react": "^18.3.18","@types/react-dom": "^18.3.5","@vitejs/plugin-react-swc": "^4.1.0","cross-env": "^10.1.0","jsdom": "^27.0.0","lightningcss": "^1.30.2","properties-file": "^3.6.1","ts-node": "^10.9.2","uuid": "^13.0.0","vite": "^7.1.10","vite-plugin-checker": "^0.11.0","vite-plugin-dts": "^4.5.4","vitest": "^3.2.4"},"author": {"name": "Red Hat, Inc.","url": "https://www.keycloak.org/"},"license": "Apache-2.0","repository": {"type": "git","url": "https://github.com/keycloak/keycloak.git","directory": "js/apps/admin-ui"},"homepage": "https://www.keycloak.org/"}

admin-ui/vite.config.ts

import react from "@vitejs/plugin-react-swc";import { readFileSync } from "node:fs";import path from "path";import { getProperties } from "properties-file";import { defineConfig, loadEnv } from "vite";import { checker } from "vite-plugin-checker";import dts from "vite-plugin-dts";import { configDefaults } from "vitest/config";

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");
  const external = ["react", "react/jsx-runtime", "react-dom"];
  const plugins = [
    react(),
    checker({ typescript: true }),
    {
      name: "message-bundle-transformer",
      resolveId(source) {
        if (source === "message-bundle") {
          return source;
        }
        return null;
      },
      load(id) {
        if (id === "message-bundle") {
          let properties = {};
          if (process.env.NODE_ENV === "development") {
            properties = getProperties(
              readFileSync(
                "./maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties",
              ),
            );
          }
          return {
            code: `export default ${JSON.stringify(properties)};`,
          };
        }
        return null;
      },
    },
  ];
  const input = env.LIB ? undefined : "src/main.tsx";
  if (env.LIB) {
    external.push("react-router-dom");
    external.push("react-i18next");
    plugins.push(dts({ insertTypesEntry: true }));
  }

  const lib = env.LIB
    ? {
        outDir: "lib",
        lib: {
          entry: path.resolve(__dirname, "src/index.ts"),
          formats: ["es"],
        },
      }
    : {
        outDir: "target/classes/theme/keycloak.v2/admin/resources",
        external: ["src/index.ts"],
      };
  return {
    base: "",
    server: {
      origin: "http://localhost:5174",
      port: 5174,
    },
    build: {
      ...lib,
      sourcemap: true,
      target: "esnext",
      modulePreload: false,
      cssMinify: "lightningcss",
      manifest: true,
      rollupOptions: {
        input,
        external,
      },
    },
    plugins,
    test: {
      watch: false,
      environment: "jsdom",
      exclude: [...configDefaults.exclude, "./test/**"],
      server: {
        deps: {
          inline: [/@patternfly\.*/],
        },
      },
    },
  };
});

解决方案

直接访问Vite的5174端口会404,因为Keycloak Admin UI依赖Keycloak后端的认证和路由代理,不能独立访问。正确的运行步骤如下:

  1. 确保依赖构建完成
    在keycloak-main根目录执行pnpm install,安装所有依赖。然后进入js/apps/admin-ui目录运行pnpm run dev,此时Vite会自动构建依赖的ui-shared和keycloak-admin-client库,等待Vite提示服务就绪。

  2. 修改Keycloak启动命令,指定开发UI的代理地址
    停止之前运行的Keycloak后端,重新执行启动命令时添加--admin-ui-dev-url参数,指向Vite的开发服务器地址:

    kc.bat start-dev --admin-ui-dev-url=http://localhost:5174
    

    这个参数会让Keycloak将/admin路径的请求代理到Vite的开发服务器,同时处理认证流程。

  3. 通过Keycloak的Admin路径访问
    不要直接访问localhost:5174,而是打开浏览器访问Keycloak的Admin页面:http://localhost:8080/admin(默认Keycloak端口是8080,如果修改过端口请对应调整)。此时Keycloak会自动代理到Vite的开发服务器,加载你本地的Admin UI代码,并且支持热更新。

  4. 额外检查项

    • 确认vite.config.ts中的input配置在非LIB模式下为src/main.tsx,你的配置已经正确设置。
    • 检查maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties文件是否存在,Vite插件需要读取这个文件加载国际化信息,如果不存在可以从Keycloak的主题目录复制一份过来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 02:54:54