Docker环境下NextJs集成Keycloak认证遇ECONNREFUSED错误求助
Docker环境下NextJS 14集成Keycloak 25.0.1的连接问题解决方法
问题根源
容器内部网络与宿主机网络相互隔离:
- NextJS容器内的
localhost指向容器自身,而非宿主机,因此用http://localhost:8080访问Keycloak会被拒绝 - 直接用容器名
keycloak:8080作为issuer,会导致浏览器重定向到这个仅容器内部可访问的地址,宿主机浏览器无法打开
解决方案
需要区分**服务器端(NextAuth API路由)和客户端(浏览器)**的Keycloak访问地址,同时配置Keycloak客户端的合法跳转规则。
1. 修正Keycloak客户端配置
登录Keycloak管理控制台(http://localhost:8080/admin),找到nextjs realm下的nextjs_client客户端:
- Valid Redirect URIs:添加
http://localhost:3000/api/auth/callback/keycloak - Web Origins:添加
http://localhost:3000 - 保存配置
2. 修改环境变量
在.env文件中分别定义服务器端和客户端使用的Keycloak地址:
KEYCLOAK_CLIENT_ID=nextjs_client KEYCLOAK_CLIENT_SECRET=abcdefghijklmnopqrs # 服务器端(NextJS容器内部访问Keycloak用) KEYCLOAK_ISSUER_SERVER=http://keycloak:8080/realms/nextjs # 客户端(浏览器访问Keycloak用) KEYCLOAK_ISSUER_CLIENT=http://localhost:8080/realms/nextjs NEXT_AUTH_SECRET=your_nextauth_secret_here # 可通过`openssl rand -hex 32`生成随机值
3. 更新NextAuth配置
修改pages/api/auth/[...nextauth].ts,分别指定服务器端和客户端的Keycloak接口地址:
import NextAuth from "next-auth" import KeycloakProvider from "next-auth/providers/keycloak" export const authOptions = { debug: true, secret: process.env.NEXT_AUTH_SECRET, providers: [ KeycloakProvider({ clientId: process.env.KEYCLOAK_CLIENT_ID || "", clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || "", // 服务器端调用用容器内部地址 issuer: process.env.KEYCLOAK_ISSUER_SERVER, // 客户端重定向用宿主机地址 authorization: { url: `${process.env.KEYCLOAK_ISSUER_CLIENT}/protocol/openid-connect/auth`, }, // 服务器端token/userinfo/jwks接口调用用容器内部地址 token: { url: `${process.env.KEYCLOAK_ISSUER_SERVER}/protocol/openid-connect/token`, }, userinfo: { url: `${process.env.KEYCLOAK_ISSUER_SERVER}/protocol/openid-connect/userinfo`, }, jwks_endpoint: `${process.env.KEYCLOAK_ISSUER_SERVER}/protocol/openid-connect/certs`, // 可选:自定义用户信息映射,如需开启取消注释 // profile(profile) { // return { // id: profile.sub, // name: profile.name ?? profile.preferred_username, // email: profile.email, // } // }, }), ], } export default NextAuth(authOptions)
4. 优化Docker启动顺序(可选)
添加健康检查确保MySQL完全启动后再启动Keycloak,避免因依赖服务未就绪导致的启动失败,修改docker-compose.yml:
version: '3.8' services: nextjs: build: . ports: - '3000:3000' depends_on: - mysql - keycloak volumes: - .:/app command: sh -c "npm run dev" mysql: image: mysql:8.0 ports: - '3306:3306' command: ["mysqld", "--init-file=/docker-entrypoint-initdb.d/init.sql"] volumes: - mysql-data:/var/lib/mysql - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] interval: 5s timeout: 5s retries: 5 environment: MYSQL_ROOT_PASSWORD: your_mysql_root_password # 需设置MySQL根密码 keycloak: image: quay.io/keycloak/keycloak:25.0.1 # 固定版本,避免自动更新导致兼容性问题 depends_on: mysql: condition: service_healthy ports: - 8080:8080 volumes: - keycloak-data:/opt/keycloak/data - ./keycloak-config:/opt/keycloak/data/import command: ["start-dev", "--import-realm"] environment: KEYCLOAK_ADMIN: admin # 设置Keycloak管理员账号 KEYCLOAK_ADMIN_PASSWORD: admin # 设置管理员密码 volumes: mysql-data: keycloak-data:
验证步骤
- 重启所有容器:
docker-compose down && docker-compose up -d - 访问NextJS应用(
http://localhost:3000),点击登录按钮 - 检查是否正常跳转到Keycloak登录页面,登录后是否能成功返回NextJS应用
内容的提问来源于stack exchange,提问作者user23455176
相关产品推荐
相关产品推荐

