Browse Source

fixed issue #5301, fixed caching_sha2_password full auth

jianghang.loujh 4 months ago
parent
commit
7ee551cbf7

+ 24 - 15
driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/MysqlConnector.java

@@ -196,6 +196,7 @@ public class MysqlConnector {
         }
         HandshakeInitializationPacket handshakePacket = new HandshakeInitializationPacket();
         handshakePacket.fromBytes(body);
+        // default utf8(33)
         byte serverCharsetNumber = (handshakePacket.serverCharsetNumber != 0) ? handshakePacket.serverCharsetNumber : 33;
         SslMode sslMode = sslInfo != null ? sslInfo.getSslMode() : SslMode.DISABLED;
         if (sslMode != SslMode.DISABLED) {
@@ -223,10 +224,11 @@ public class MysqlConnector {
         serverVersion = handshakePacket.serverVersion; // 记录serverVersion
         logger.info("handshake initialization packet received, prepare the client authentication packet to send");
         // 某些老协议的 server 默认不返回 auth plugin,需要使用默认的 mysql_native_password
-        String authPluginName = (handshakePacket.authPluginName != null
-                                 && handshakePacket.authPluginName.length > 0) ? new String(
-                                     handshakePacket.authPluginName) : "mysql_native_password";
-        logger.info("auth plugin: {}", authPluginName);
+        String authPluginName = "mysql_native_password";
+        if (handshakePacket.authPluginName != null && handshakePacket.authPluginName.length > 0) {
+            authPluginName = new String(handshakePacket.authPluginName);
+        }
+        logger.info("auth ClientAuthenticationSHA2Packet: {}", authPluginName);
         boolean isSha2Password = false;
         ClientAuthenticationPacket clientAuth;
         if ("caching_sha2_password".equals(authPluginName)) {
@@ -295,22 +297,29 @@ public class MysqlConnector {
                     body = PacketManager.readBytes(channel, header.getPacketBodyLength(), timeout);
                 } else if ("caching_sha2_password".equals(pluginName)) {
                     byte[] scramble = authData;
-                    try {
-                        encryptedPassword = MySQLPasswordEncrypter.scrambleCachingSha2(getPassword().getBytes(),
-                            scramble);
-                    } catch (DigestException e) {
-                        throw new RuntimeException("can't encrypt password that will be sent to MySQL server.", e);
-                    }
-                    header = authSwitchAfterAuth(encryptedPassword, header);
-                    body = PacketManager.readBytes(channel, header.getPacketBodyLength(), timeout);
-                    assert body != null;
                     if (body[0] == 0x01 && body[1] == 0x04) {
-                        // fixed issue https://github.com/alibaba/canal/pull/4767, support mysql 8.0.30+
+                        // support full auth
+                        // clientAuth提前采用了sha2编码,会减少一次auth交互
                         header = cachingSha2PasswordFullAuth(channel, header, getPassword().getBytes(), scramble);
                         body = PacketManager.readBytes(channel, header.getPacketBodyLength(), timeout);
                     } else {
-                        header = PacketManager.readHeader(channel, 4);
+                        try {
+                            encryptedPassword = MySQLPasswordEncrypter.scrambleCachingSha2(getPassword().getBytes(),
+                                    scramble);
+                        } catch (DigestException e) {
+                            throw new RuntimeException("can't encrypt password that will be sent to MySQL server.", e);
+                        }
+                        header = authSwitchAfterAuth(encryptedPassword, header);
                         body = PacketManager.readBytes(channel, header.getPacketBodyLength(), timeout);
+                        assert body != null;
+                        if (body[0] == 0x01 && body[1] == 0x04) {
+                            // fixed issue https://github.com/alibaba/canal/pull/4767, support mysql 8.0.30+
+                            header = cachingSha2PasswordFullAuth(channel, header, getPassword().getBytes(), scramble);
+                            body = PacketManager.readBytes(channel, header.getPacketBodyLength(), timeout);
+                        } else {
+                            header = PacketManager.readHeader(channel, 4);
+                            body = PacketManager.readBytes(channel, header.getPacketBodyLength(), timeout);
+                        }
                     }
                 } else {
                     header = authSwitchAfterAuth(encryptedPassword, header);