Docker部署Spring后端对接Keycloak遇InvalidBearerTokenException问题求助
问题根源
Docker容器跨网络部署时,Spring后端配置的issuer-uri使用网关IP,但Keycloak签发JWT时,默认用自身容器的内部地址(如容器名、内网IP)作为iss字段值,导致两者完全不匹配,触发InvalidBearerTokenException: Invalid issuer错误。
解决方案
1. 统一Keycloak的Issuer签发地址
Keycloak 17+基于Quarkus重构后,建议使用KC_HOSTNAME系列参数配置外部访问地址,避免旧版KEYCLOAK_FRONTEND_URL引发的认证流程冲突:
# Keycloak容器启动环境变量 KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=admin KC_HOSTNAME=你的网关IP或域名 # 例如192.168.1.100或example.com KC_HOSTNAME_PORT=8180 # Keycloak对外暴露的端口 KC_PROXY=edge # 无反向代理时设为none,有代理时设为edge
该配置会让Keycloak用指定的外部地址签发JWT的iss字段,同时保证前端(如Postman)能正常获取令牌。
2. 同步Spring后端的Issuer配置
修改Spring的application.yml,将KEYCLOAK_HOST设置为上面的KC_HOSTNAME值,确保issuer-uri与Keycloak签发的iss字段完全一致:
jwk-set-uri: http://${KEYCLOAK_HOST:你的网关IP或域名}:${KEYCLOAK_PORT:8180}/auth/realms/myrealm/protocol/openid-connect/certs issuer-uri: http://${KEYCLOAK_HOST:你的网关IP或域名}:${KEYCLOAK_PORT:8180}/auth/realms/myrealm
同时确保Spring容器能访问该地址:
- 若两者在不同Docker网络,可将它们加入同一个自定义网络;
- 或确认网关IP的端口映射已正确配置,Spring容器能通过网关访问Keycloak。
3. 验证令牌一致性
用Postman获取令牌后,解码查看iss字段,确认其与Spring配置的issuer-uri完全匹配(包括协议、IP/域名、端口、路径)。
4. 排查网络连通性
在Spring容器内部执行以下命令,确认能正常获取Keycloak的OIDC配置:
curl http://你的网关IP:8180/auth/realms/myrealm/.well-known/openid-configuration
能返回配置则说明网络连通正常,Spring可拉取JWKS密钥完成令牌验证。
代码优化提示
若仅使用单个Keycloak实例,可简化oauth2ResourceServer配置,减少多Issuer管理的复杂度:
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())))
(需自行注入JwtDecoder bean,基于配置的jwk-set-uri和issuer-uri构建)
内容的提问来源于stack exchange,提问作者lemario

