
# 连接数据库报错Access denied
#### 场景描述
客户端连接数据库异常，返回错误：Error 1045: Access denied for user xxx
#### 处理方法
1. 连接了错误的主机 问题原因：业务连接了错误的数据库主机，该主机上相应用户或客户端IP没有权限访问。
   解决方案：仔细检查要连接的数据库主机名，确保正确。
   
2. 用户不存在 问题原因：客户端连接时，使用的用户不存在。
   解决方案：
   - 使用管理员账户登录数据库，执行如下命令检查目标用户是否存在。
     ```
     SELECT User FROM mysql.user WHERE User='xxx';
     ```
     
   
   - 如果用户不存在，创建相应用户。
     ```
     CREATE USER 'xxx'@'xxxxxx' IDENTIFIED BY 'xxxx';
     ```
     
     
3. 用户存在，但客户端IP无访问权限 问题原因：客户端使用的用户存在，但是客户端IP没有该数据库的访问权限。
   解决方案：
   - 使用管理员账户登录数据库，执行如下命令，检查目标用户允许哪些客户端IP连接。
     ```
     SELECT Host, User FROM mysql.user WHERE User='xxx';
     ```
     
   
   - 如果上述查询出的Host不包含客户端IP所在网段，则需要赋予相应访问权限。例如，赋予test用户192.168.0网段访问权限。
     ```
     GRANT ALL PRIVILEGES ON *.* TO'root'@'192.168.0.%' IDENTIFIED BY 'password' WITH GRANT OPTION; 
     FLUSH PRIVILEGES;
     ```
     
    
4. 密码错误 问题原因：用户对应的密码错误，或忘记密码
   解决方案：
   - 确定目标密码是否错误，由于密码用于身份验证，因此无法从MySQL以明文形式读取用户密码，但可以将密码的哈希字符串与目标密码的"PASSWORD"函数值进行比较，确定目标密码是否正确，示例SQL语句：
     ```
     mysql> SELECT Host, User, authentication_string, PASSWORD('12345') FROM mysql.user WHERE User='test'; 
     +-----------+------+-------------------------------------------+-------------------------------------------+
     | Host      | User | authentication_string                     | PASSWORD('12345')                         | 
     +-----------+------+-------------------------------------------+-------------------------------------------+
     | %         | test | *6A23DC5E7446019DC9C1778554ED87BE6BA61041 | *00A51F3F48415C7D4E8908980D443C29C69B60C9 | 
     +-----------+------+-------------------------------------------+-------------------------------------------+
     2 rows in set, 1 warning (0.00 sec)
     ```
     从上面例子可以看出，PASSWORD('12345')的哈希值与authentication_string列不匹配，这表明目标密码"12345"是错误的。
     
   
   - 如果需要重置用户密码，参考如下SQL语句：
     ```
     set password for 'test'@'%' = 'new_password';
     ```
     
    
5. 密码包含特殊字符被Bash转义 问题原因：Linux默认的Bash环境下，使用命令行连接数据库，用户密码中包含特殊字符会被环境转义，导致密码失效。
   例如，在Bash环境下，用户test的密码为"test$123"，使用命令mysql -hxxx -u test -ptest$123，连接数据库会报错ERROR 1045 (28000): Access denied。
   解决方案：通过用单引号将密码括起来，防止Bash解释特殊字符。
   ```
   mysql -hxxx -u test -p'test$123'
   ```
   
6. 用户设置了REQUIRE SSL，但客户端使用非SSL连接 排查思路：
   - 排查报错用户名是否强制使用SSL连接，执行：show create user 'xxx'，如果出现"REQUIRE SSL"属性，说明该用户必须使用SSL连接。
   
   - 排查是否使用过如下类似语句给用户授权。
     ```
     GRANT ALL PRIVILEGES ON . TO 'ssluser'@'localhost' IDENTIFIED BY 'zdh1234' REQUIRE SSL;
     ```
     
   
   - 检查目标用户的ssl_type值，如果不为空，说明该用户需要使用SSL连接。
     ```
     SELECT User, Host, ssl_type FROM mysql.user WHERE User='xxx';
     ```
     
   
   
   解决方案：
   - 客户端使用SSL方式数据库连接，请参考[SSL连接方式](https://support.huaweicloud.com/usermanual-rds-mysql/rds_mysql_connect_05.html)。
   
   - 去除用户SSL连接权限，参考命令：**ALTER USER 'test'@'xxxxx' REQUIRE NONE;**
    
 
