WSO2 API Manager v4.1.0 WebSocket连接403握手失败求助
WSO2 API Manager v4.1.0 WebSocket 403握手失败排查指南
问题描述
直接连接Publisher提供的WebSocket API URL可正常接收事件,但通过API Manager代理访问时,客户端握手失败,wso2carbon.log中出现Invalid handshake response getStatus: 403错误。
错误日志
TID: [-1234] [] [2023-01-24 10:10:18,892] WARN {org.apache.synapse.core.axis2.AsyncCallback} - Executing fault handler due to exception encountered TID: [-1234] [] [2023-01-24 10:10:18,892] INFO {org.apache.synapse.mediators.builtin.LogMediator} - {api:EventNotificationFeed-carcyayu:vv1} STATUS = Executing default 'fault' sequence, ERROR_CODE = 0, ERROR_MESSAGE = Invalid handshake response getStatus: 403 TID: [-1234] [] [2023-01-24 10:10:18,892] INFO {org.apache.axis2.engine.AxisEngine} - [MessageContext: logID=728bbb294f5b69e363a7319861bb41d3f89e0c7852a44cf5] Invalid handshake response getStatus: 403 TID: [-1234] [] [2023-01-24 10:10:18,892] ERROR {org.apache.synapse.core.axis2.AsyncCallback} - Invalid handshake response getStatus: 403 io.netty.handler.codec.http.websocketx.WebSocketClientHandshakeException: Invalid handshake response getStatus: 403 at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker13.verify(WebSocketClientHandshaker13.java:272) at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker.finishHandshake(WebSocketClientHandshaker.java:304) at org.wso2.carbon.websocket.transport.WebSocketClientHandler.handleHandshake(WebSocketClientHandler.java:127) at org.wso2.carbon.websocket.transport.WebSocketClientHandler.channelRead0(WebSocketClientHandler.java:249) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1371) at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1234) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1283) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:449) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:829) TID: [-1234] [] [2023-01-24 10:10:18,892] WARN {org.apache.synapse.core.axis2.AsyncCallback} - Executing fault handler due to exception encountered TID: [-1234] [] [2023-01-24 10:10:18,893] INFO {org.apache.synapse.mediators.builtin.LogMediator} - {api:EventNotificationFeed-carcyayu:vv1} STATUS = Executing default 'fault' sequence, ERROR_CODE = 0, ERROR_MESSAGE = Invalid handshake response getStatus: 403 TID: [-1234] [] [2023-01-24 10:10:18,904] ERROR {org.apache.synapse.core.axis2.AsyncCallback} - Invalid handshake response getStatus: 403 io.netty.handler.codec.http.websocketx.WebSocketClientHandshakeException: Invalid handshake response getStatus: 403 at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker13.verify(WebSocketClientHandshaker13.java:272) at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker.finishHandshake(WebSocketClientHandshaker.java:304) at org.wso2.carbon.websocket.transport.WebSocketClientHandler.handleHandshake(WebSocketClientHandler.java:127) at org.wso2.carbon.websocket.transport.WebSocketClientHandler.channelRead0(WebSocketClientHandler.java:249) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1371) at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1234) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1283) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:449) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:829)
排查步骤与解决方案
1. 验证API订阅与权限
- 登录API Manager控制台,确认该WebSocket API已被目标应用订阅,且订阅状态为
Active。 - 检查应用是否被禁用,以及订阅的环境(如Production/Sandbox)与调用环境一致。
- 确认调用方使用的认证凭证(如OAuth2令牌)拥有该API的访问权限,令牌的
scope需匹配API配置的要求。
2. 检查WebSocket传输配置
- 打开
<APIM_HOME>/repository/conf/deployment.toml文件,确保WebSocket传输已启用:[transport.ws] enable = true [transport.wss] enable = true - 若启用了自定义中介流,暂时移除所有WebSocket相关的中介逻辑,测试是否能正常握手,排除中介拦截导致的403。
3. 处理CORS与Origin头问题
- WebSocket握手请求会携带
Origin头,若API Manager的CORS配置未允许客户端的Origin,会触发403。 - 在API的CORS设置中,添加客户端的Origin地址,或临时设置
Allow Any Origin进行测试。
4. 检查认证拦截器配置
- 若API启用了认证,确保WebSocket握手阶段的请求能正确传递认证凭证。部分客户端可能在握手时未携带令牌,需调整客户端逻辑或API的认证配置,允许握手请求携带凭证。
5. 排查后端服务权限
- 虽然直接连接后端正常,但通过APIM代理时,APIM使用的后端连接用户可能缺少权限。检查APIM与后端服务之间的认证配置,确保APIM的后端身份拥有访问WebSocket服务的权限。
内容的提问来源于stack exchange,提问作者Yaroslav
相关产品推荐
相关产品推荐

