是这样我想知道 jdbc 与 mysql 交互,源码上网边看边查到 mysqlIO.class ,问题是我如果 jdbc 里面数据库名或者密码错了(虽然我知道错的),底层是怎么判断的 ,目的是要这套判断,和判断结果,套用在自己的数据上面,相当于借用他们的标准套在我们的数据库上面,以后也好形成统一。 还望各位大佬们不吝赐教,指条明路。我是菜鸡,只管喷。 祝大佬 情绪稳定,睡眠良好,头发浓密
目前代码看到这里 mysqlIO.class
void secureAuth411(Buffer packet, int packLength, String user, String password, String database, boolean writeClientParams) throws SQLException { String enc = this.getEncodingForHandshake(); if (packet == null) { packet = new Buffer(packLength); }
if (writeClientParams) {
if (this.use41Extensions) {
if (this.versionMeetsMinimum(4, 1, 1)) {
packet.writeLong(this.clientParam);
packet.writeLong((long)this.maxThreeBytes);
this.appendCharsetByteForHandshake(packet, enc);
packet.writeBytesNoNull(new byte[23]);
} else {
packet.writeLong(this.clientParam);
packet.writeLong((long)this.maxThreeBytes);
}
} else {
packet.writeInt((int)this.clientParam);
packet.writeLongInt(this.maxThreeBytes);
}
}
// 设置用户名
packet.writeString(user, enc, this.connection);
if (password.length() != 0) {
packet.writeByte((byte)20);
try {
// 设置密码
packet.writeBytesNoNull(Security.scramble411(password, this.seed, this.connection.getPasswordCharacterEncoding()));
} catch (NoSuchAlgorithmException var11) {
throw SQLError.createSQLException(Messages.getString("MysqlIO.95") + Messages.getString("MysqlIO.96"), "S1000", this.getExceptionInterceptor());
} catch (UnsupportedEncodingException var12) {
throw SQLError.createSQLException(Messages.getString("MysqlIO.95") + Messages.getString("MysqlIO.96"), "S1000", this.getExceptionInterceptor());
}
} else {
packet.writeByte((byte)0);
}
// 设置数据库名
if (this.useConnectWithDb) {
packet.writeString(database, enc, this.connection);
} else {
packet.writeByte((byte)0);
}
if ((this.serverCapabilities & 1048576) != 0) {
this.sendConnectionAttributes(packet, enc, this.connection);
}
// 向 Mysql 服务器发送登录信息包(用户名、密码、此 Socket 连接默认选择的数据库)
this.send(packet, packet.getPosition());
byte var10002 = this.packetSequence;
this.packetSequence = (byte)(var10002 + 1);
byte savePacketSequence = var10002;
// 读取 Mysql 服务器登录检验后发送的状态信息,如果成功就返回,如果登录失败则抛出异常
Buffer reply = this.checkErrorPacket();
if (reply.isLastDataPacket()) {
++savePacketSequence;
this.packetSequence = savePacketSequence;
packet.clear();
String seed323 = this.seed.substring(0, 8);
packet.writeString(Util.newCrypt(password, seed323));
this.send(packet, packet.getPosition());
this.checkErrorPacket();
}
}
在mysqlIO源码里面有个this.readFully(this.mysqlInput, reuse.getByteBuffer(), 0, packetLength); 这个应该是读取发送登录信息后mysql服务端返回的响应
private void checkErrorPacket(Buffer resultPacket)
这个应该是读取发送登录信息后mysql服务端返回的响应,登录正常直接返回,错误就抛异常。
不看mysql端 就是怎么知道密码错误或用户名错误返回的异常或者是报错代码就行。利用这个错误在自己的数据库上面 发生同错误也会报这样的异常或错误
我脑子卡死了一团浆糊
1
xiangyuecn 2021-11-04 17:48:27 +08:00
你的段位不是菜鸡,是会写数据库驱动的牛逼大佬🐶
|
2
AlbertChen 2021-11-04 18:03:04 +08:00
先看 mysql 协议,再看源码应该好理解一些吧
https://segmentfault.com/a/1190000023747225 https://javamana.com/2021/01/20210113051649490Q.html |
3
misaka19000 2021-11-04 18:12:43 +08:00
直接 tcpdump 抓包看
|
4
zjsxwc 2021-11-04 18:39:55 +08:00 via Android
膜拜大佬
|
5
Lyv5 OP @AlbertChen 好的我研究下
|
6
Lyv5 OP @xiangyuecn 大哥我真菜鸡
|
7
lei2j 2021-11-05 09:30:44 +08:00
你都搞这个了,那我就是菜鸡中的弱鸡了
|
8
yizmaoaa 2021-11-05 09:56:54 +08:00
其实你在驱动里是看不到怎么判断用户名密码是错的,驱动包也只是根据数据库的协议发包的。至于用户名密码是对的还是错的,是你驱动包发数据过去,然后 Mysql Server 里判断然后给客户端返回异常信息的
|
10
DsuineGP 2021-11-05 14:14:20 +08:00
@Lyv5 可以看一下 mycat 鉴权这一块的代码,也是用 java 写的,大致的逻辑跟你想实现的很像,拦截 mysql 一端的错误信息并包装一层放回给客户端
|
11
vinle 2021-11-05 14:49:52 +08:00
首先膜拜一下,楼主过于谦虚,能为一个新的数据库作贡献是非常强的了。
然后对于 LZ 的问题, “底层是怎么判断的” :mysql 的 server 与 client 通信已经算是很高层的实现了,至于底层,楼主没说清楚到底多底层,看楼主的代码注释应该是指:Client (使用 jdbc 的客户端程序)识别 Server(数据库服务器)返回的 Packet (响应)的过程中,怎么判断 mysql 的错误类型的。 其实楼主已经分析得非常完整了,因为就是 MysqlIO 类的 checkErrorPacket 来判断的,更完整的调用链是:/ secureAuth411 / -> / checkErrorPacket() / -> / checkErrorPacket(-1) / -> / checkErrorPacket(resultPacket) / -> / 你要的逻辑 / “不看 mysql 端 就是怎么知道密码错误...” : 关于这个,一般来说这些错误代码的规范,都会有公开的文档,方便 mysql 社区参考,所以不用担心一般不需要深入到 mysql 的源码里边,对于特定版本的规范也应该不一样,我就随便找了个版本索引一下了: https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-error-sqlstates.html ,进去后直接搜“PASSWORD”大概率就能找到你想要的了。 |