M S Q L 拒绝连接的解决办法!

本文详细介绍了当遇到MySQL中root用户访问权限问题时的解决步骤,包括如何授权root用户从任意IP或本地访问数据库,刷新权限使更改生效,以及如何删除特定主机上的用户。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

报错:
Caused by: java.sql.SQLException: Unable to open a test connection to the given database. JDBC url = jdbc:mysql://VM1:3306/hive?characterEncoding=UTF-8, username = root. Terminating connection pool (set lazyInit to true if you expect to start your database after your app). Original Exception: ------
java.sql.SQLException: Access denied for user ‘root’@‘VM1’ (using password: YES)

解决方案:
1、授权

设置用户root可以在任意IP下被访问:

grant all privileges on . to root@"%" identified by “新密码”;

设置用户root可以在本地被访问:

grant all privileges on . to root@“localhost” identified by “新密码”

刷新权限使之生效

flush privileges;

2、删除对应主机用户

use mysql;

select host,user from user;

drop user ‘username’@‘host’;

/* MQTT解析器测试函数 */ void mqtt_parser_test(void) { uint8_t packet_buffer[256]; uint32_t result; uint8_t i; uint8_t passed = 1; CircularQueue q; /* 测试数据数组 */ uint8_t test_data1[] = { 0x30, 0x0A, /* PUBLISH QoS0 + 剩余长度 */ 0x00, 0x03, 'a', 'b', 'c', /* 主题 */ 0x00, 0x00, /* 报文标识符 (QoS0时忽略) */ 'h', 'e', 'l', 'l', 'o' /* 负载 */ }; uint8_t test_data2[] = {0x38, 0x00}; /* 无效的PUBLISH */ uint8_t test_data3[] = { 0x30, /* PUBLISH QoS0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0x80 /* 非法的剩余长度格式 */ }; uint8_t test_data4[] = { 0x30, 0x05, /* PUBLISH QoS0 + 剩余长度 */ 0x00, 0x03, 'a', 'b' /* 缺少一个字节 */ }; uint8_t test_data5[] = {0x30, 0x80}; /* 不完整的剩余长度 */ uint8_t test_data6[] = { /* 报文1: CONNECT */ 0x10, 0x10, /* 固定报头 */ 0x00, 0x04, 'M', 'Q', 'T', 'T', /* 协议名 */ 0x04, /* 协议级别 */ 0x02, /* 连接标志 */ 0x00, 0x0A, /* 保持活动 */ 0x00, 0x03, 'c', 'i', 'd', /* 客户端ID */ /* 报文2: PUBLISH QoS1 */ 0x32, 0x0A, /* PUBLISH QoS1 */ 0x00, 0x03, 't', 'o', 'p', /* 主题 */ 0x00, 0x01, /* 报文标识符 */ 'm', 's', 'g' /* 负载 */ }; uint8_t test_data7[] = { 0x10, 0x13, /* CONNECT + 剩余长度 */ 0x00, 0x04, 'M', 'Q', 'T', 'T', /* 协议名 */ 0x04, /* 协议级别 */ 0x02, /* 连接标志 */ 0x00, 0x0A, /* 保持活动 */ 0x00, 0x05, 'c', 'l', 'i', 'e', 'n', /* 客户端ID */ 0x00, 0x04, 'u', 's', 'e', 'r', /* 用户名 */ 0x00, 0x04, 'p', 'a', 's', 's' /* 密码 */ }; /* 初始化队列 */ Queue_Init(&q); /* 通过串口输出测试信息 */ printf("\r\n===== MQTT解析器测试开始 =====\r\n"); /* 测试用例1: 有效PUBLISH报文 (QoS0) */ printf("\r\n测试用例1: 有效PUBLISH报文 (QoS0)\r\n"); Queue_Writes(&q, test_data1, sizeof(test_data1)); result = mqtt_parser(&q, packet_buffer); if (result == sizeof(test_data1)) { printf(" - 测试通过: 成功解析报文,长度=%lu\r\n", result); } else { printf(" - 测试失败: 预期长度=%lu, 实际长度=%lu\r\n", (uint32_t)sizeof(test_data1), result); passed = 0; } /* 清空队列 */ Queue_Init(&q); /* 测试用例2: 无效报文类型 */ printf("\r\n测试用例2: 无效报文类型\r\n"); Queue_Writes(&q, test_data2, sizeof(test_data2)); result = mqtt_parser(&q, packet_buffer); if (result == 0) { printf(" - 测试通过: 正确拒绝无效报文\r\n"); } else { printf(" - 测试失败: 预期0, 实际%lu\r\n", result); passed = 0; } /* 清空队列 */ Queue_Init(&q); /* 测试用例3: 剩余长度格式错误 */ printf("\r\n测试用例3: 剩余长度格式错误\r\n"); Queue_Writes(&q, test_data3, sizeof(test_data3)); result = mqtt_parser(&q, packet_buffer); if (result == 0) { printf(" - 测试通过: 正确检测剩余长度错误\r\n"); } else { printf(" - 测试失败: 预期0, 实际%lu\r\n", result); passed = 0; } /* 清空队列 */ Queue_Init(&q); /* 测试用例4: 报文不完整 */ printf("\r\n测试用例4: 报文不完整\r\n"); Queue_Writes(&q, test_data4, sizeof(test_data4)); result = mqtt_parser(&q, packet_buffer); if (result == 0) { printf(" - 测试通过: 正确处理不完整报文\r\n"); } else { printf(" - 测试失败: 预期0, 实际%lu\r\n", result); passed = 0; } /* 清空队列 */ Queue_Init(&q); /* 测试用例5: 超时处理 */ printf("\r\n测试用例5: 超时处理\r\n"); Queue_Writes(&q, test_data5, sizeof(test_data5)); /* 模拟多次调用以触发超时 */ for (i = 0; i <= MQTT_PARSE_TIMEOUT; i++) { result = mqtt_parser(&q, packet_buffer); } if (result == 0 && Queue_Length(&q) == 0) { printf(" - 测试通过: 正确处理超时并丢弃数据\r\n"); } else { printf(" - 测试失败: 队列长度=%u, 结果=%lu\r\n", Queue_Length(&q), result); passed = 0; } /* 清空队列 */ Queue_Init(&q); /* 测试用例6: 多个报文连续解析 */ printf("\r\n测试用例6: 多个报文连续解析\r\n"); Queue_Writes(&q, test_data6, sizeof(test_data6)); /* 解析第一个报文 */ result = mqtt_parser(&q, packet_buffer); if (result == 16) { printf(" - 报文1解析成功: 长度=%lu\r\n", result); /* 解析第二个报文 */ result = mqtt_parser(&q, packet_buffer); if (result == 12) { printf(" - 报文2解析成功: 长度=%lu\r\n", result); printf(" - 测试通过: 成功解析多个报文\r\n"); } else { printf(" - 测试失败: 报文2预期12, 实际%lu\r\n", result); passed = 0; } } else { printf(" - 测试失败: 报文1预期16, 实际%lu\r\n", result); passed = 0; } /* 清空队列 */ Queue_Init(&q); /* 测试用例7: 有效CONNECT报文 */ printf("\r\n测试用例7: 有效CONNECT报文\r\n"); Queue_Writes(&q, test_data7, sizeof(test_data7)); result = mqtt_parser(&q, packet_buffer); if (result == sizeof(test_data7)) { printf(" - 测试通过: 成功解析CONNECT报文\r\n"); } else { printf(" - 测试失败: 预期长度=%lu, 实际长度=%lu\r\n", (uint32_t)sizeof(test_data7), result); passed = 0; } /* 最终测试结果 */ printf("\r\n===== 测试结果 =====\r\n"); if (passed) { printf("所有测试用例通过!\r\n"); } else { printf("部分测试用例失败!\r\n"); } printf("====================\r\n"); } uint32_t mqtt_parser(CircularQueue *q, uint8_t *packet_buff) { static uint8_t state = 0; // 解析状态 static uint32_t total_length = 0; // 报文总长度 static uint8_t rlen_bytes = 0; // 剩余长度字节数 static uint8_t timeout_cnt = 0; // 超时计数器 uint32_t i; uint8_t packet_type; // 报文类型 // 剩余长度解析 uint8_t byte, multiplier = 1; uint32_t rlen = 0; rlen_bytes = 0; while (!Queue_Empty(q)) { // 超时处理机制 if (timeout_cnt >= MQTT_PARSE_TIMEOUT) { Queue_MoveReadIndex(q, 1); // 丢弃首字节 state = 0; timeout_cnt = 0; printf("\n[超时] 丢弃无效数据\n"); continue; } switch (state) { case 0: // 固定报头解析状态 { if (Queue_Length(q) < 2) { timeout_cnt++; return 0; // 数据不足,等待下次调用 } Queue_PeekAt(q, 0, &packet_type); // 获取报文类型 // 严格验证报文类型 if (!validate_mqtt_header(packet_type)) { Queue_MoveReadIndex(q, 1); // 仅丢弃错误字节 printf("\n[错误] 无效报文类型: 0x%02X\n", packet_type); timeout_cnt = 0; continue; } do { if (Queue_Length(q) < (2 + rlen_bytes)) { timeout_cnt++; return 0; // 数据不足 } Queue_PeekAt(q, 1 + rlen_bytes, &byte); rlen += (byte & 0x7F) * multiplier; // MQTT协议合规性检查 if (rlen_bytes >= 4 && (byte & 0x80)) { Queue_MoveReadIndex(q, 1 + rlen_bytes); printf("\n[错误] 剩余长度格式错误\n"); timeout_cnt = 0; continue; } multiplier *= 128; rlen_bytes++; } while (byte & 0x80); total_length = 1 + rlen_bytes + rlen; state = 1; timeout_cnt = 0; break; } case 1: // 报文数据读取状态 { if (Queue_Length(q) < total_length) { timeout_cnt++; return 0; // 数据不足 } // 批量读取报文数据 for (i = 0; i < total_length; i++) { Queue_PeekAt(q, i, &packet_buff[i]); printf("%02X ", packet_buff[i]); } Queue_MoveReadIndex(q, total_length); // 移除已处理数据 printf("\n[成功] 报文类型:0x%02X 长度:%u\n", packet_buff[0], total_length); state = 0; timeout_cnt = 0; return total_length; // 返回成功解析的长度 } } } return 0; // 队列为空时返回0 } // 返回实际写入字节数,便于调用方处理 uint8_t Queue_Writes(CircularQueue *q, uint8_t *data, uint8_t length) { uint8_t used; uint8_t free; uint8_t actual_length; uint8_t cont_free; ENTER_CRITICAL(); // 进入临界区 // 计算剩余空间 used = (q->write - q->read) & (QUEUE_SIZE - 1); free = QUEUE_SIZE - 1 - used; // 保留一个位置区分满/空状态 // 计算实际可写入长度 actual_length = (length > free) ? free : length; if (actual_length == 0) { EXIT_CRITICAL(); return 0; } // 计算连续写入空间(从 write 指针到缓冲区末尾) cont_free = QUEUE_SIZE - q->write; if (actual_length <= cont_free) { // 空间连续:直接复制 memcpy(&q->buffer[q->write], data, actual_length); q->write += actual_length; } else { // 空间分两段:先复制尾部,再复制头部剩余部分 memcpy(&q->buffer[q->write], data, cont_free); memcpy(q->buffer, data + cont_free, actual_length - cont_free); q->write = actual_length - cont_free; // 回绕到头部 } // 确保 write 指针在 [0, QUEUE_SIZE-1] 范围内 q->write &= (QUEUE_SIZE - 1); // 等价于取模运算 EXIT_CRITICAL(); // 退出临界区 return actual_length; } /* MQTT解析器测试函数 */ void mqtt_parser_test(void)这个函数执行不符合预期,结果入下===== MQTT解析器测试开始 ===== 测试用例1: 有效PUBLISH报文 (QoS0) 30 0A 00 03 61 62 63 00 00 68 65 6C [成功] 报文类型:0x30 长度:12 - 测试失败: 预期长度=14, 实际长度=12 测试用例2: 无效报文类型 [错误] 无效报文类型: 0x38 - 测试通过: 正确拒绝无效报文 测试用例3: 剩余长度格式错误 [错误] 剩余长度格式错误 - 测试通过: 正确检测剩余长度错误 测试用例4: 报文不完整 - 测试通过: 正确处理不完整报文 测试用例5: 超时处理 [超时] 丢弃无效数据 - 测试失败: 队列长度=1, 结果=0 测试用例6: 多个报文连续解析 10 10 00 04 4D 51 54 54 04 02 00 0A 00 03 63 69 64 32 [成功] 报文类型:0x10 长度:18 - 测试失败: 报文1预期16, 实际18 测试用例7: 有效CONNECT报文 10 13 00 04 4D 51 54 54 04 02 00 0A 00 05 63 6C 69 65 6E 00 04 [成功] 报文类型:0x10 长度:21 - 测试失败: 预期长度=31, 实际长度=21 ===== 测试结果 ===== 部分测试用例失败! ====================
最新发布
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值