Skip to content

paxoscn/mysql-protocol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LICENSE Language

README in English: README_EN.md

MySQL协议Java实现

改造自https://github.com/mheath/netty-mysql-codec

这个项目适用于:

  • 实现自有数据库时并允许任何MySQL兼容客户端进行连接.
  • 代理任何数据源并将其封装为MySQL服务.
  • 学习MySQL协议.

快速开始

运行单元测试

为了确保代码下载完整, 你可以运行MySqlListenerTest.java 来确认单元测试是否可以正确运行.

这个单元测试会启动一个MySQL服务,对它的任何查询都只会返回'Hello World !'. 随后它会启动一个JDBC访问并发送一句SQL到服务器, 检查查询结果并关闭服务.

创建自己的MySQL服务

首先你需要实现SqlEngine

public class YourSqlEngine implements SqlEngine {
}

要对客户端发过来的SQL进行响应,你需要实现query().

@Override
public void query(ResultSetWriter resultSetWriter, String database, String userName, byte[] scramble411, byte[] authSeed, String sql) throws IOException {
    // 在结果集中放入一列,名为'col1'
    // 该调用必须在任意一次writeRow()之前
    resultSetWriter.writeColumns(List.of(new QueryResultColumn("col1", "varchar(255)")));

    // 在结果集中放入一行,值为'Hello World !'
    resultSetWriter.writeRow(List.of("Hello World !"));

    // 最后需要调用finish()方法结束响应
    resultSetWriter.finish();
}

为了保护你的服务不被未授权人员访问, 你还需要实现authenticate().

@Override
public void authenticate(String database, String userName, byte[] scramble411, byte[] authSeed) throws IOException {
    // 只允许用户名'github'
    String validUser = "github";
    if (!userName.equals(validUser)) {
        throw new IOException(new IllegalAccessException("Authentication failed: User " + userName + " is not allowed to connect"));
    }
    
    // 只允许密码'123456'
    String validPassword = "123456";
    
    // 对密码进行SHA1及编码
    String validPasswordSha1 = SHAUtils.SHA(validPassword, SHAUtils.SHA_1);
    String validScramble411WithSeed20 = Utils.scramble411(validPasswordSha1, authSeed);
    
    // 比较密码编码结果
    if (!Utils.compareDigest(validScramble411WithSeed20, Base64.getEncoder().encodeToString(scramble411))) {
        throw new IOException(new IllegalAccessException("Authentication failed: Validation failed"));
    }
}

实现完毕后, 你可以把实现类传入MySqlListener,当它实例化后会自动监听指定TCP端口.

// 启动并监听端口3307
new MySqlListener(3307, 100, new YourSqlEngine());

// 为了有足够时间来进行客户端连接,可以在这里sleep一段时间.
Thread.sleep(1000L * 60 * 10);

启动服务后, 你可以用任何MySQL客户端来进行连接,以下以MySQL命令行客户端为例.

mysql -h127.0.0.1 -P3307 -ugithub -p123456 dummy_db
> select * from dummy_table;
+---------------+
| col1          |
+---------------+
| Hello World ! |
+---------------+
1 row in set (0.006 sec)

开源协议

本项目使用Apache 2.0协议. 详情请见: LICENSE.

告知

  • 感谢 mheath 提供的基础代码.
  • 最小Java版本: JDK11. (JDK8在测试中)
  • 联系方式 - 微信: 95634620 邮件: [email protected]

Releases

No releases published

Packages

No packages published

Languages