ホームページ >データベース >mysql チュートリアル >認証パッケージと mysql プロトコルのコードの詳細な紹介

認証パッケージと mysql プロトコルのコードの詳細な紹介

黄舟
黄舟オリジナル
2017-03-08 14:06:241313ブラウズ


git


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

概要

Mysql クライアントが mysql サーバーにログインするには、まず対話型プロセスが必要です。クライアント クライアントによって送信された最初のハンドシェイク パケット。ハンドシェイク パケットを受信した後、クライアントは認証パケットをサーバーに返します。ここでは以下のように認証パッケージを解析します。

client                 server
   |-------connect------>|
   |                     |
   |<-----handshake------|
   |                     |
   |---authentication--->|
   |                     |

mysql通信メッセージ構造

認証パッケージと mysql プロトコルのコードの詳細な紹介

ペイロード認証パッケージ

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
  }

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

認証パッケージの操作

1. 認証パッケージクラス

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com
 * 
blog: http://www.php.cn/;/pre>
 * 

mysql auth packet.

 */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 
  1. 暗号化および復号化ツール

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com
 * 
blog: http://www.php.cn/;/pre>
 * 

a security util .

 */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 
  1. テストクラス

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com
 * 
<b>blog: </b>http://www.php.cn/;/pre>
 * <p>test auth packet.</p>
 */public class AuthPacketTest {
    @Test
    public void produce() {        
    // handshake packet'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;
    }
}


以上が認証パッケージと mysql プロトコルのコードの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。