/* * Copyright 2015 Liu Huanting. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package fm.liu.timo.mysql.handler; import fm.liu.timo.mysql.CharsetUtil; import fm.liu.timo.mysql.SecurityUtil; import fm.liu.timo.mysql.connection.MySQLConnection; import fm.liu.timo.mysql.packet.EOFPacket; import fm.liu.timo.mysql.packet.ErrorPacket; import fm.liu.timo.mysql.packet.HandshakePacket; import fm.liu.timo.mysql.packet.OkPacket; import fm.liu.timo.mysql.packet.Reply323Packet; import fm.liu.timo.net.NIOHandler; import fm.liu.timo.net.handler.BackendConnectHandler; /** * MySQL连接认证 * @author Liu Huanting 2015年5月9日 */ public class AuthenticatorHandler implements NIOHandler { private final MySQLConnection con; private final BackendConnectHandler handler; public AuthenticatorHandler(MySQLConnection con, BackendConnectHandler handler) { this.con = con; this.handler = handler; } @Override public void handle(byte[] data) { switch (data[4]) { case OkPacket.FIELD_COUNT: HandshakePacket handshake = con.getHandshake(); if (handshake == null) { prepare(data); con.auth(); break; } con.setHandler(new ConnectorHandler(con)); con.setAuthenticated(true); if (handler != null) { handler.acquired(con); } break; case ErrorPacket.FIELD_COUNT: ErrorPacket err = new ErrorPacket(); err.read(data); String msg = new String(err.message); con.close(msg); throw new RuntimeException(msg); case EOFPacket.FIELD_COUNT: auth323(data[3]); break; default: handshake = con.getHandshake(); if (handshake == null) { prepare(data); // 发送认证数据包 con.auth(); break; } else { throw new RuntimeException("unknown Packet!"); } } } private void auth323(byte packetId) { // 发送323响应认证数据包 Reply323Packet r323 = new Reply323Packet(); r323.packetId = ++packetId; String pass = con.getPassword(); if (pass != null && pass.length() > 0) { byte[] seed = con.getHandshake().seed; r323.seed = SecurityUtil.scramble323(pass, new String(seed)).getBytes(); } r323.write(con); } private void prepare(byte[] data) { HandshakePacket packet = new HandshakePacket(); packet.read(data); con.setHandshake(packet); con.setThreadID(packet.threadId); int charsetIndex = packet.serverCharsetIndex & 0xff; String charset = CharsetUtil.getCharset(charsetIndex); if (charset == null) { } if (charsetIndex != con.getVariables().getCharsetIndex()) { } boolean autocommit = false; if ((packet.serverStatus & 0x02) == 0x02) { autocommit = true; } con.getVariables().setAutocommit(autocommit); } public void error(Throwable t) { handler.error(t.getMessage(), con); } }