迁移Identity Server至v6.0.0后无法在Api Manager DevPortal添加沙箱OAuth2密钥
WSO2 AM 4.1.0 搭配 IS 6.0.0 无法添加沙箱OAuth2密钥问题解决
问题场景
- WSO2 API Manager 4.1.0 搭配 Identity Server 5.11.0 时,可正常在DevPortal中添加沙箱OAuth2密钥;
- 将Identity Server升级至6.0.0后,同版本AM 4.1.0无法完成该操作。
错误日志
TID: [-1234] [api/am/devportal] [2022-09-26 13:58:10,497] ERROR {org.wso2.carbon.apimgt.rest.api.util.exception.GlobalThrowableMapper} - An unknown exception has been captured by the global exception mapper. feign.codec.DecodeException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 19 column 1 path $ at feign.AsyncResponseHandler.decode(AsyncResponseHandler.java:119) at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:87) at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) at com.sun.proxy.$Proxy467.getApplication(Unknown Source) at org.wso2.carbon.apimgt.impl.AMDefaultKeyManagerImpl.mapOAuthApplication_aroundBody20(AMDefaultKeyManagerImpl.java:581) at org.wso2.carbon.apimgt.impl.AMDefaultKeyManagerImpl.mapOAuthApplication(AMDefaultKeyManagerImpl.java:561) at org.wso2.carbon.apimgt.impl.APIConsumerImpl.mapExistingOAuthClient_aroundBody78(APIConsumerImpl.java:2517) at org.wso2.carbon.apimgt.impl.APIConsumerImpl.mapExistingOAuthClient(APIConsumerImpl.java:2452) at org.wso2.carbon.apimgt.rest.api.store.v1.impl.ApplicationsApiServiceImpl.applicationsApplicationIdMapKeysPost(ApplicationsApiServiceImpl.java:1101 ) at org.wso2.carbon.apimgt.rest.api.store.v1.ApplicationsApi.applicationsApplicationIdMapKeysPost(ApplicationsApi.java:281) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:201) at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104) at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307) at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:265) at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:225) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:304) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:217) at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:279) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.wso2.carbon.identity.context.rewrite.valve.TenantContextRewriteValve.invoke(TenantContextRewriteValve.java:107) at org.wso2.carbon.identity.authz.valve.AuthorizationValve.invoke(AuthorizationValve.java:110) at org.wso2.carbon.identity.auth.valve.AuthenticationValve.invoke(AuthenticationValve.java:102) at org.wso2.carbon.tomcat.ext.valves.CompositeValve.continueInvocation(CompositeValve.java:101) at org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer.invokeValves(TomcatValveContainer.java:49) at org.wso2.carbon.tomcat.ext.valves.CompositeValve.invoke(CompositeValve.java:62) at org.wso2.carbon.tomcat.ext.valves.CarbonStuckThreadDetectionValve.invoke(CarbonStuckThreadDetectionValve.java:146) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) at org.wso2.carbon.tomcat.ext.valves.CarbonContextCreatorValve.invoke(CarbonContextCreatorValve.java:58) at org.wso2.carbon.tomcat.ext.valves.RequestCorrelationIdValve.invoke(RequestCorrelationIdValve.java:126) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 19 column 1 path $ at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226) at com.google.gson.Gson.fromJson(Gson.java:932) at com.google.gson.Gson.fromJson(Gson.java:897) at feign.gson.GsonDecoder.decode(GsonDecoder.java:50) at feign.AsyncResponseHandler.decode(AsyncResponseHandler.java:115) ... 63 more Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 19 column 1 path $ at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:386) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215) ... 67 more
问题分析
日志核心错误Expected BEGIN_OBJECT but was STRING表明:AM的Feign客户端调用IS的getApplication接口时,IS 6.0.0返回的JSON响应结构与AM 4.1.0预期格式不匹配。IS 6.0.0对OAuth应用相关API的响应结构做了调整,而AM 4.1.0的密钥管理器代码仍基于IS 5.x的响应格式解析,导致Gson反序列化失败,最终无法完成沙箱密钥的添加/映射。
解决方案
1. 安装官方兼容补丁
WSO2针对AM 4.1.0与IS 6.0.0的兼容性问题,发布了专门的密钥管理器适配补丁。下载对应补丁jar包后,放入AM的<AM_HOME>/repository/components/dropins目录,重启AM服务即可。
2. 自定义代码适配
若无法使用官方补丁,可手动修改AM侧密钥管理器的解析逻辑:
- 找到
org.wso2.carbon.apimgt.impl.AMDefaultKeyManagerImpl类的mapOAuthApplication方法 - 调整Gson解析逻辑,兼容IS 6.0.0返回的新响应格式(如字段类型变更、字段增删等)
- 重新编译该类并替换AM中的对应jar包
3. 临时绕过方案
若需快速恢复功能,可手动在IS 6.0.0中创建OAuth应用,获取客户端ID和密钥后,在AM DevPortal中手动将该应用映射到目标API应用,跳过自动创建/映射流程。
4. 配置验证
检查AM的deployment.toml中IS相关配置:
[apim.key_manager] service_url = "https://<IS_HOST>:<IS_PORT>" username = "<IS_SERVICE_ACCOUNT_USERNAME>" password = "<IS_SERVICE_ACCOUNT_PASSWORD>"
确保配置的服务账号在IS 6.0.0中拥有Internal/application_mgt_view、Internal/application_mgt_update等必要权限。
内容的提问来源于stack exchange,提问作者Bobi Lungu
相关产品推荐
相关产品推荐

