Heim > Datenbank > MySQL-Tutorial > Eine detaillierte Einführung in das Authentifizierungspaket und den Code des MySQL-Protokolls

Eine detaillierte Einführung in das Authentifizierungspaket und den Code des MySQL-Protokolls

黄舟
Freigeben: 2017-03-08 14:06:24
Original
1277 Leute haben es durchsucht


git


https://github.com/sea-boat/mysql-protocol

Übersicht

Die Anmeldung des MySQL-Clients beim MySQL-Server erfordert einen interaktiven Prozess. Zunächst sendet der Server ein erstes Handshake-Paket an den Client. Nach Erhalt des Handshake-Pakets sendet der Client ein Authentifizierungspaket an den Server zurück . Wie folgt wird hier das Authentifizierungspaket analysiert.

client                 server
   |-------connect------>|
   |                     |
   |<-----handshake------|
   |                     |
   |---authentication--->|
   |                     |
Nach dem Login kopieren

MySQL-Kommunikationsnachrichtenstruktur

Eine detaillierte Einführung in das Authentifizierungspaket und den Code des MySQL-Protokolls

Nutzlast Authentifizierungspaket

4              capability flags, CLIENT_PROTOCOL_41 always set
4              max-packet size
1              character set
string[23]     reserved (all [0])
string[NUL]    username
  if capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA {
lenenc-int     length of auth-response
string[n]      auth-response
  } else if capabilities & CLIENT_SECURE_CONNECTION {
1              length of auth-response
string[n]      auth-response
  } else {
string[NUL]    auth-response
  }
  if capabilities & CLIENT_CONNECT_WITH_DB {
string[NUL]    database
  }
  if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL]    auth plugin name
  }
  if capabilities & CLIENT_CONNECT_ATTRS {
lenenc-int     length of all key-values
lenenc-str     key
lenenc-str     value
   if-more data in &#39;length of all key-values&#39;, more keys and value pairs
  }
Nach dem Login kopieren

Weitere Details: http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse

Authentifizierungspaket-Betrieb

1. Authentifizierungspakettyp

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
*
<b>blog: </b>http://www.php.cn/;/pre>
 * <p>mysql auth packet.</p>
 */public class AuthPacket extends MySQLPacket {
    private static final byte[] FILLER = new byte[23];    
    public long clientFlags;    
    public long maxPacketSize;    
    public int charsetIndex;    
    public byte[] extra;    
    public String user;    
    public byte[] password;    
    public String database;    
    public void read(byte[] data) {
        MySQLMessage mm = new MySQLMessage(data);
        packetLength = mm.readUB3();
        packetId = mm.read();
        clientFlags = mm.readUB4();
        maxPacketSize = mm.readUB4();
        charsetIndex = (mm.read() & 0xff);        
        int current = mm.position();        
        int len = (int) mm.readLength();        
        if (len > 0 && len < FILLER.length) {            
        byte[] ab = new byte[len];
            System.arraycopy(mm.bytes(), mm.position(), ab, 0, len);            
            this.extra = ab;
        }
        mm.position(current + FILLER.length);
        user = mm.readStringWithNull();
        password = mm.readBytesWithLength();        
        if (((clientFlags & Capabilities.CLIENT_CONNECT_WITH_DB) != 0)
                && mm.hasRemaining()) {
            database = mm.readStringWithNull();
        }
    }    public void write(ByteBuffer buffer) throws IOException {
        BufferUtil.writeUB3(buffer, calcPacketSize());
        buffer.put(packetId);
        BufferUtil.writeUB4(buffer, clientFlags);
        BufferUtil.writeUB4(buffer, maxPacketSize);
        buffer.put((byte) charsetIndex);
        buffer.put(FILLER);        if (user == null) {
            buffer.put((byte) 0);
        } else {
            BufferUtil.writeWithNull(buffer, user.getBytes());
        }        if (password == null) {
            buffer.put((byte) 0);
        } else {
            BufferUtil.writeWithLength(buffer, password);
        }        if (database == null) {
            buffer.put((byte) 0);
        } else {
            BufferUtil.writeWithNull(buffer, database.getBytes());
        }
    }    @Override
    public int calcPacketSize() {        
    int size = 32;// 4+4+1+23;
        size += (user == null) ? 1 : user.length() + 1;
        size += (password == null) ? 1 : BufferUtil.getLength(password);
        size += (database == null) ? 1 : database.length() + 1;        
        return size;
    }    @Override
    protected String getPacketInfo() {        
    return "MySQL Authentication Packet";
    }

}
Nach dem Login kopieren
  1. Verschlüsselungs- und Entschlüsselungstool

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
*
<b>blog: </b>http://www.php.cn/;/pre>
 * <p>a security util .</p>
 */public class SecurityUtil {

    public static final byte[] scramble411(byte[] pass, byte[] seed)            
    throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-1");        
        byte[] pass1 = md.digest(pass);
        md.reset();        
        byte[] pass2 = md.digest(pass1);
        md.reset();
        md.update(seed);        
        byte[] pass3 = md.digest(pass2);        
        for (int i = 0; i < pass3.length; i++) {
            pass3[i] = (byte) (pass3[i] ^ pass1[i]);
        }        return pass3;
    }    public static final String scramble323(String pass, String seed) {        
    if ((pass == null) || (pass.length() == 0)) {            
    return pass;
        }        
        byte b;        
        double d;        
        long[] pw = hash(seed);        
        long[] msg = hash(pass);        
        long max = 0x3fffffffL;        
        long seed1 = (pw[0] ^ msg[0]) % max;        
        long seed2 = (pw[1] ^ msg[1]) % max;        
        char[] chars = new char[seed.length()];        
        for (int i = 0; i < seed.length(); i++) {
            seed1 = ((seed1 * 3) + seed2) % max;
            seed2 = (seed1 + seed2 + 33) % max;
            d = (double) seed1 / (double) max;
            b = (byte) java.lang.Math.floor((d * 31) + 64);
            chars[i] = (char) b;
        }
        seed1 = ((seed1 * 3) + seed2) % max;
        seed2 = (seed1 + seed2 + 33) % max;
        d = (double) seed1 / (double) max;
        b = (byte) java.lang.Math.floor(d * 31);        
        for (int i = 0; i < seed.length(); i++) {
            chars[i] ^= (char) b;
        }        return new String(chars);
    }    private static long[] hash(String src) {        
    long nr = 1345345333L;        
    long add = 7;        
    long nr2 = 0x12345671L;        
    long tmp;        
    for (int i = 0; i < src.length(); ++i) {            
    switch (src.charAt(i)) {            
    case &#39; &#39;:            
    case &#39;\t&#39;:                
    continue;            
    default:
                tmp = (0xff & src.charAt(i));
                nr ^= ((((nr & 63) + add) * tmp) + (nr << 8));
                nr2 += ((nr2 << 8) ^ nr);
                add += tmp;
            }
        }        
        long[] result = new long[2];
        result[0] = nr & 0x7fffffffL;
        result[1] = nr2 & 0x7fffffffL;        
        return result;
    }

}
Nach dem Login kopieren
  1. Testklasse

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
*
<b>blog: </b>http://www.php.cn/;/pre>
 * <p>test auth packet.</p>
 */public class AuthPacketTest {
    @Test
    public void produce() {        
    // handshake packet&#39;s rand1 and rand2
        byte[] rand1 = RandomUtil.randomBytes(8);        
        byte[] rand2 = RandomUtil.randomBytes(12);        
        byte[] seed = new byte[rand1.length + rand2.length];
        System.arraycopy(rand1, 0, seed, 0, rand1.length);
        System.arraycopy(rand2, 0, seed, rand1.length, rand2.length);

        AuthPacket auth = new AuthPacket();
        auth.packetId = 0;
        auth.clientFlags = getClientCapabilities();
        auth.maxPacketSize = 1024 * 1024 * 16;
        auth.user = "seaboat";        try {
            auth.password = SecurityUtil
                    .scramble411("seaboat".getBytes(), seed);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        auth.database = "test";

        ByteBuffer buffer = ByteBuffer.allocate(256);
        auth.write(buffer);
        buffer.flip();        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes, 0, bytes.length);
        String result = HexUtil.Bytes2HexString(bytes);
        System.out.println(result);
        assertTrue(Integer.valueOf(result.substring(0, 2), 16) == result
                .length() / 2 - 4);

        AuthPacket auth2 = new AuthPacket();
        auth2.read(bytes);
        assertTrue(auth2.database.equals("test"));
    }    protected int getClientCapabilities() {        
    int flag = 0;
        flag |= Capabilities.CLIENT_LONG_PASSWORD;
        flag |= Capabilities.CLIENT_FOUND_ROWS;
        flag |= Capabilities.CLIENT_LONG_FLAG;
        flag |= Capabilities.CLIENT_CONNECT_WITH_DB;
        flag |= Capabilities.CLIENT_ODBC;
        flag |= Capabilities.CLIENT_IGNORE_SPACE;
        flag |= Capabilities.CLIENT_PROTOCOL_41;
        flag |= Capabilities.CLIENT_INTERACTIVE;
        flag |= Capabilities.CLIENT_IGNORE_SIGPIPE;
        flag |= Capabilities.CLIENT_TRANSACTIONS;
        flag |= Capabilities.CLIENT_SECURE_CONNECTION;        
        return flag;
    }
}
Nach dem Login kopieren


Das obige ist der detaillierte Inhalt vonEine detaillierte Einführung in das Authentifizierungspaket und den Code des MySQL-Protokolls. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage