Skip to content

鸿蒙系统微信小游戏无法连接websocket,安卓正常 #54

@VkingLangzi

Description

@VkingLangzi

服务器接收Socket代码

`import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import org.springframework.stereotype.Component;

/**

  • TLS版本检测器

  • 通过分析SSL握手包来准确获取客户端使用的TLS版本
    */
    @component
    public class TlsVersionDetector extends ChannelInboundHandlerAdapter {

    @OverRide
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (msg instanceof ByteBuf) {
    ByteBuf buf = (ByteBuf) msg;
    String clientIp = ctx.channel().remoteAddress().toString();

         // 尝试解析TLS握手包
         String tlsVersion = parseTlsVersion(buf);
         if (tlsVersion != null) {
             // 根据TLS版本决定日志级别
             if (isSecureTlsVersion(tlsVersion)) {
                 LogP.info("检测到客户端 {} 使用TLS版本: {}", clientIp, tlsVersion);
             } else {
                 LogP.warn("检测到客户端 {} 使用不安全的TLS版本: {} (建议升级到TLS1.2或TLS1.3)", clientIp, tlsVersion);
             }
             // 解析完成后移除自己,避免影响后续处理
             ctx.pipeline().remove(this);
         } else {
             LogP.info("无法检测到客户端 {} 使用TLS版本: {}", clientIp, tlsVersion);
         }
     }
    
     // 继续传递消息
     super.channelRead(ctx, msg);
    

    }

    /**

    • 判断是否为安全的TLS版本
      */
      private boolean isSecureTlsVersion(String tlsVersion) {
      return "TLSv1.2".equals(tlsVersion) || "TLSv1.3".equals(tlsVersion);
      }

    /**

    • 解析TLS握手包中的版本信息
      */
      private String parseTlsVersion(ByteBuf buf) {
      if (buf.readableBytes() < 5) {
      return null;
      }

      // 保存当前读取位置
      int readerIndex = buf.readerIndex();

      try {
      // TLS记录格式:
      // Byte 0: Content Type (0x16 = Handshake)
      // Byte 1-2: Protocol Version
      // Byte 3-4: Length

       byte contentType = buf.readByte();
       if (contentType != 0x16) { // 不是握手包
           return null;
       }
      
       // 读取协议版本 (2 bytes)
       byte majorVersion = buf.readByte();
       byte minorVersion = buf.readByte();
       return decodeTlsVersion(majorVersion, minorVersion);
      

      } catch (Exception e) {
      LogP.debug("解析TLS版本时出错: {}", e.getMessage());
      return null;
      } finally {
      // 恢复读取位置
      buf.readerIndex(readerIndex);
      }
      }
      /**

    • 将版本字节转换为TLS版本字符串
      */
      private String decodeTlsVersion(byte major, byte minor) {
      if (major == 3) {
      switch (minor) {
      case 0:
      return "SSLv3.0";
      case 1:
      return "TLSv1.0";
      case 2:
      return "TLSv1.1";
      case 3:
      return "TLSv1.2";
      case 4:
      return "TLSv1.3";
      default:
      return "TLS未知版本(3." + (minor & 0xFF) + ")";
      }
      } else if (major == 2) {
      return "SSLv2.0";
      } else {
      return "未知协议版本(" + (major & 0xFF) + "." + (minor & 0xFF) + ")";
      }
      }

    @OverRide
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    // 如果出现异常,移除自己并继续
    ctx.pipeline().remove(this);
    super.exceptionCaught(ctx, cause);
    }
    }`

报错日志

2025-09-13T15:56:38.681+0800 [soccer3 PVP server_NETTY_WORKER_1] ERROR n.g.l.netty.MessageDataServerHandleio.netty.handler.ssl.ReferenceCountedOpenSslEngine$OpenSslHandshakeException: error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN
io.netty.handler.codec.DecoderException: io.netty.handler.ssl.ReferenceCountedOpenSslEngine$OpenSslHandshakeException: error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:499)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:61)
at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:425)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:66)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.netty.handler.ssl.ReferenceCountedOpenSslEngine$OpenSslHandshakeException: error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.newSSLExceptionForError(ReferenceCountedOpenSslEngine.java:1377)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.shutdownWithError(ReferenceCountedOpenSslEngine.java:1089)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.sslReadErrorResult(ReferenceCountedOpenSslEngine.java:1399)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1325)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1426)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1469)
at io.netty.handler.ssl.SslHandler$SslEngineType$1.unwrap(SslHandler.java:223)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1353)
at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1257)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1297)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions