首页 > 数据库 >55 mysql 的登录认证流程

55 mysql 的登录认证流程

时间:2024-09-24 16:28:28浏览次数:3  
标签:String 55 认证 密码 mysql byte salt digest 客户端


前言

这里我们来看一下 mysql 的认证的流程 

我们这里仅仅看 我们最常见的一个 认证的处理流程

我们经常会登录的时候 碰到各种异常信息

 

 

认证失败的大体流程

大概的流程是这样 

客户端和服务器建立连接之后, 服务器向客户端发送 salt

然后 客户端根据 salt 将客户端传入的密码加密之后, 以及相关登录信息传递给服务器 

然后 服务器进行验证, 验证失败, 响应对应的错误信息给客户端 

55 mysql 的登录认证流程_服务器

 

服务器发送 salt 的信息如下 

55 mysql 的登录认证流程_login_02

 

客户端发送的认证请求如下 

55 mysql 的登录认证流程_客户端_03

 

 服务器响应的认证失败信息如下 

55 mysql 的登录认证流程_connection_04

 

服务器发送 slat 的信息是在这里, 这里的 salt 是随机生成的 

55 mysql 的登录认证流程_connection_05

 

读取客户端的加密之后的信息 

55 mysql 的登录认证流程_login_06

 

然后是 密码的验证, 我们这里的流程是这样, 这里 数据库用 root 用户没有密码, 但是客户端这边传入了密码, 因此这里直接响应了 CA_AUTH_USER_REDENTIALS

55 mysql 的登录认证流程_mysql_07

  

然后接着是 响应错误信息给客户端, 这里是响应 1045 ACCESS_DENIED_ERROR “Access denied for user 'root'@'192.168.220.1' (using password: YES)”

55 mysql 的登录认证流程_mysql_08

 

 

Access denied for user 'root'@'192.168.220.1' (using password: YES) 

这里同上, 几种情况 

首先需要传递密码, 其次是 root用户密码为空 或者 密码不对 会响应如下问题

上面演示了 mysql 密码为空, 但是 我输入了密码 之后的校验情况

我们现在来看一下 密码对不上的情况

用到了一些加密的特性来验证, 客户端输入的密文和数据库是否匹配 

scramble_arg 表示的是客户端传入的密文, message 表示数据库的密文, hash_stage2 表示此次登录验证的 slat 

55 mysql 的登录认证流程_login_09

 

 

Access denied for user 'root'@'192.168.220.1' (using password: NO) 

这种情况就是 该用户有密码, 但是客户端 未传递 密码

验证是在这里, 如果数据库中该用户也没有密码, 直接 OK, 否则 响应 CR_AUTH_USER_CREDENTIALS

到后面的错误输出环节, 得到的错误信息 就是上面

55 mysql 的登录认证流程_connection_10

 

 

客户端加密, 服务器验证的逻辑仿写 

这里主要是 实现了一个 客户端这边 传递的密码的加密方式的处理

以及 服务器这边 验证 客户端秘钥, 服务器秘钥 的一个验证方式

可以参考学习一下, 需要导入 mysql-driver, netty 等等相关工具 

salt 是服务器的 ServerGreeting 传递回来的, 是一个 20自己的随机字节序列

clientPwd 是根据用户名, 密码 salt 加密之后的一个结果 

serverPwd 是 mysql 中 mysql.user 库中该用户记录的 authentication_string 秘钥序列

/**
 * Test09MysqlLoginEncrypt
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2023/8/9 9:31
 */
public class Test09MysqlLoginEncrypt {

    // Test09MysqlLoginEncrypt
    public static void main(String[] args) throws Exception {

        String salt = ("2c 4f 04 2a 30 13 69 71").replaceAll("\\s+", "")
                + ("03 17 0a 1d 64 55 7e 68 1f 19 73 0a").replaceAll("\\s+", "");
        String clientPwd = "012cb36acb2a4c77217d8d70dc43e058c1c6448a";
        String serverPwd = "81F5E21E35407D884A6CD4A731AEBFB6AF209E1B";

        String clientPwdEncoded = ByteBufUtil.hexDump(clientEncryptPwd("root", "root", salt));
        boolean clientPwdIfMatch = checkClientPwdIfMatch(clientPwd, salt, serverPwd);
        AssertUtils.assert0(clientPwd, clientPwdEncoded, " check if clientEncryptPwd match ");
        AssertUtils.assert0(clientPwdIfMatch, " checkClientPwdIfMatch match ");
        int x = 0;

    }

    /**
     * checkClientPwdIfMatch
     *
     * @return boolean
     * @author Jerry.X.He
     * @date 2023/8/9 10:31
     */
    public static boolean checkClientPwdIfMatch(String clientPwd, String salt, String serverPwd) {
        byte[] saltBytes = ByteBufUtil.decodeHexDump(salt);
        byte[] pwdInClient = ByteBufUtil.decodeHexDump(clientPwd);
        byte[] pwdInDb = ByteBufUtil.decodeHexDump(serverPwd);

        MessageDigest digest = DigestUtils.getSha1Digest();
        digest.reset();
        digest.update(saltBytes);
        digest.update(pwdInDb);
        byte[] pwdSaltUpdated = digest.digest();

        my_crypt(pwdSaltUpdated, pwdSaltUpdated, pwdInClient);

        digest.reset();
        digest.update(pwdSaltUpdated);
        byte[] pwdFinalUpdated = digest.digest();

        boolean clientPwdEqualsDb = ByteBufUtil.hexDump(pwdFinalUpdated).equalsIgnoreCase(serverPwd);
        return clientPwdEqualsDb;
    }

    /**
     * clientEncryptPwd
     *
     * @return byte[]
     * @author Jerry.X.He
     * @date 2023/8/9 10:22
     */
    public static byte[] clientEncryptPwd(String username, String password, String salt) {
        MysqlNativePasswordPlugin plugin = new MysqlNativePasswordPlugin();
        NativeProtocol protocol = new MyNativeProtocol(new NullLogger(""));
        plugin.init(protocol);
        NativePacketPayload fromServer = new NativePacketPayload(ByteBufUtil.decodeHexDump(salt));
        List<NativePacketPayload> toSaveList = new ArrayList<>();
        plugin.setAuthenticationParameters(username, password);
        plugin.nextAuthenticationStep(fromServer, toSaveList);
        return toSaveList.get(0).getByteBuffer();
    }

    /**
     * my_crypt
     *
     * @return void
     * @author Jerry.X.He
     * @date 2023/8/9 10:21
     */
    public static void my_crypt(byte[] to, byte[] s1, byte[] s2) {
        for (int i = 0; i < s1.length; i++) {
            to[i] = (byte) (s1[i] ^ s2[i]);
        }
    }

    /**
     * Test09MysqlLoginEncrypt
     *
     * @author Jerry.X.He
     * @version 1.0
     * @date 2023/8/9 10:19
     */
    private static class MyNativeProtocol extends NativeProtocol {
        public MyNativeProtocol(Log logger) {
            super(logger);
        }

        @Override
        public String getPasswordCharacterEncoding() {
            return "UTF-8";
        }
    }

}

 

运行处理, 信息如下 

55 mysql 的登录认证流程_login_11

 

 

完 

 

 

 

标签:String,55,认证,密码,mysql,byte,salt,digest,客户端
From: https://blog.51cto.com/u_16608712/12100770

相关文章

  • MySQL GROUP BY 分区大小写问题解析
    在数据库操作中,GROUPBY是一个常用的SQL语句,用于根据一个或多个列的值对结果集进行分组。然而,在使用MySQL时,你可能会遇到一个常见问题:大小写敏感性。本文将探讨MySQL中GROUPBY的大小写敏感性问题,并提供一些解决方案。什么是大小写敏感性?在计算机科学中,大小写敏感性是指......
  • MySQL深度探索:掌握触发器自动化与精细用户权限管理,提升数据库效能与安全
     作者简介:我是团团儿,是一名专注于云计算领域的专业创作者,感谢大家的关注 座右铭:   云端筑梦,数据为翼,探索无限可能,引领云计算新纪元 个人主页:团儿.-CSDN博客目录前言:触发器(Triggers):用户权限(UserPermissions):一.触发器1.MySQL触发器简介2.引发触发器执行的事件,......
  • docker 配置代理访问Error response from daemon: Get “https://index.docker.io/v1/
    一、前言报错原因,docker访问不到外网。并且docker不能直接依赖操作系统环境的proxy,因此需要独立配置docker的proxy才能访问外网。问题描述dockersearchmysql出现以下报错:[root@localhost~]#dockersearchmysqlErrorresponsefromdaemon:Get"https://index.docke......
  • 小米15系列旗舰新品齐获3C认证,10-11月手机大战一触即发
    【9月24日最新资讯】&nbsp;小米15标准版(型号24129PN74C)与小米15Pro(型号2410DPN6CC)接连获得国家质量监督检验检疫总局3C强制性产品认证,预示着这两款备受瞩目的旗舰新机离正式面世又迈进一大步。两者均配备最高90W超级快充技术,彰显了小米在快速充电领域持续领跑的决心。北京昌......
  • MySQL 函数的使用
    目录函数时间日期函数:字符串函数数学函数其他函数函数时间日期函数:所有的时间日期函数都是从完整的时间日期开始,根据需求进行截断;例如需要时间,则只显示时间部分;需要日期就显示日期部分;获得年月日:selectcurrent_date();+----------------+|current_......
  • pbootcms网站是使用sqlite数据库好还是使用mysql数据库好
    选择在PbootCMS网站上使用SQLite数据库还是MySQL数据库取决于几个因素,包括但不限于网站规模、预期的访问量、并发需求以及维护成本等。以下是两者的对比:SQLite架构:SQLite是一种嵌入式的关系型数据库管理系统,它不需要单独的服务器进程或系统。适用场景:适用于小型应用程序,访问量......
  • Pbootcms数据库转换教程(sqlite转mysql详细教程)
    一、准备工作下载转换所需工具:确保你有SQLiteStudio和phpMyAdmin等工具。备份现有数据:在进行任何操作之前,请确保备份现有的SQLite数据库文件。二、教程1.导出SQLite数据库打开SQLiteStudio:启动SQLiteStudio软件。定位数据库文件:找到PbootCMS的data文件夹下的.db文件。......
  • pbootcms如何将默认的sqlite转换成mysql数据库
    将PbootCMS使用的SQLite数据库转换为MySQL数据库可以通过以下几个步骤实现:准备工作备份当前SQLite数据库:在开始转换前,确保你有一个完整的SQLite数据库备份,以防转换过程中出现任何问题。准备MySQL环境:确保你的服务器上已经安装并配置好了MySQL服务,并且创建了一个新的数据库供Pb......
  • pycharm项目中mysqlclent替换使用PyMySQL
    环境:OS:Windows11Python:3.6.5以为mysqlclient一直安装不上,下面使用PyMySQL替换mysqlclient1.安装PyMySQLpipinstallPyMySQL 2.然后在你的Django项目的__init__.py文件中添加以下代码来指定Django使用PyMySQL:importpymysqlpymysql.install_as_MySQLdb() 3.......
  • 适合初学者的[JAVA]:Mysql(3:Mysql事务)
    目录说明前言事务ACID:并发事务的问题:解决方案:uddolog和redolog的区别:先了解数据库的页概念:redolog:undolog:区别:mvcc:说明本文适合刚刚学习Java的初学者,也可以当成阿岩~的随手笔记.接下来就请道友们和我一起来学习吧!如果本文有写的不对的地方,......