Keycloak核心与适配器类冲突问题求助
这个类转换异常我太熟悉了!很多用Keycloak搭配Jetty的开发者都踩过这个坑,核心原因就是类加载器隔离问题——你的项目里keycloak-jetty-adapter和keycloak-core依赖都包含了KeycloakSecurityContext类,结果在嵌入式Jetty和远程Jetty环境下,这个类被不同的类加载器加载了,JVM直接认成了两个完全不同的类型,自然转不了。
下面给你几个针对性的解决办法,按优先级来:
1. 先清理重复的依赖
keycloak-jetty-adapter本身已经依赖了keycloak-core,你完全不需要单独引入keycloak-core依赖!先把pom.xml(或build.gradle)里单独的keycloak-core依赖删掉,这是最容易解决重复类的办法。
如果确实因为某些原因必须保留keycloak-core,一定要给它设置provided scope,同时根据环境调整keycloak-jetty-adapter的scope:
- 嵌入式Jetty:
keycloak-jetty-adapter用compilescope就行,但要确保Jetty不会从其他地方加载Keycloak的类; - 远程Jetty部署:
keycloak-jetty-adapter和keycloak-core都设为provided,因为远程Jetty服务器应该已经在容器层面配置了Keycloak适配器的依赖,应用包再带一份肯定冲突。
2. 调整Jetty的类加载器配置
嵌入式Jetty
默认情况下Jetty的WebAppClassLoader会优先加载应用自身的类,但如果你的嵌入式Jetty配置了共享类加载器,就可能导致容器级和应用级的Keycloak类重复。可以通过代码调整类加载器优先级:
WebAppContext webAppContext = new WebAppContext(); // 禁用容器类加载器优先加载,让应用优先用自己打包的类 webAppContext.setParentLoaderPriority(false);
远程Jetty
去检查服务器的$JETTY_HOME/lib目录下有没有Keycloak相关的jar包,如果有,你的应用包绝对不能再包含这些jar,直接把应用里的Keycloak依赖设为provided就行。
3. 排查依赖树,排除重复引入
用依赖分析工具找出偷偷引入keycloak-core的依赖,手动排除:
- Maven:执行命令
mvn dependency:tree,搜索keycloak-core,找到重复引入的来源,然后在对应的依赖里加排除:<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-jetty-adapter</artifactId> <version>3.4.3.Final</version> <exclusions> <exclusion> <groupId>org.keycloak</groupId> <artifactId>keycloak-core</artifactId> </exclusion> </exclusions> </dependency> - Gradle:执行
./gradlew dependencies,同样找到重复的keycloak-core,用exclude处理:implementation('org.keycloak:keycloak-jetty-adapter:3.4.3.Final') { exclude group: 'org.keycloak', module: 'keycloak-core' }
4. 代码临时兼容方案(不推荐,仅应急)
如果暂时没法调整依赖和类加载器,可以用反射绕开强转问题,但这只是权宜之计,根本解决还是要处理类加载冲突:
// 不要直接强转,先获取上下文对象,再用反射调用方法 Object securityContext = request.getAttribute(KeycloakSecurityContext.class.getName()); Method getTokenMethod = securityContext.getClass().getMethod("getToken"); Object token = getTokenMethod.invoke(securityContext);
内容的提问来源于stack exchange,提问作者Cloud

