java – 在context.xml中使用两个DataSource的用户’root’@’localhost’访问被拒绝

我遇到了Java 8,MySQL Server 5.7.23,MySQL Connector for Java v5.1.45和Tomcat v9.0.12(在Ubuntu Server 18.04上运行)的问题.

我已经构建了一个简单的Java应用程序(war),它在MySQL数据库中执行查询.

我的context.xml(我放置了2个资源节点,一个用于生产,一个用于开发环境),来自真实的应用场景我从CATALINA_OPTS读取一个名为“env”的参数并用System.getProperty(“env”)读取它,应用程序可以选择要使用的相应数据源.

<Context>
    <!-- MySQL - Production -->
    <Resource
        name="prod-jdbc/ds-1" auth="Container"
        type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/testdb?useSSL=false"
        username="dbuser" password="dbUserPwd!"
        autoReconnect="true" maxTotal="10"
        minIdle="3" maxIdle="5" maxActive="10" maxWaitMillis="10000"
        removeAbandonedOnBorrow="true" removeAbandonedOnMaintenance="true"
        logAbandoned="true" removeAbandonedTimeout="1000"
        closeMethod="close" testOnBorrow="true"
        testWhileIdle="true" timeBetweenEvictionRunsMillis="60000"
        validationQueryTimeout="10" validationInterval="6000"
        validationQuery="SELECT 1"
    />

    <!-- MySQL - Development -->
    <Resource
        name="dev-jdbc/ds-1" auth="Container"
        type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/localdb?useSSL=false"
        username="root" password="root"
        autoReconnect="true" maxTotal="10"
        minIdle="3" maxIdle="5" maxActive="10"
        maxWaitMillis="10000" removeAbandonedOnBorrow="true"
        removeAbandonedOnMaintenance="true" logAbandoned="true"
        removeAbandonedTimeout="1000" closeMethod="close"
        testOnBorrow="true" testWhileIdle="true"
        timeBetweenEvictionRunsMillis="60000" validationQueryTimeout="10"
        validationInterval="6000" validationQuery="SELECT 1"
    />
</Context>

一个简单的测试类:

package main;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;
import javax.ws.rs.core.Application;

public class ConnectionTester extends Application implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        Context ctx = null; Connection con = null; Statement stmt = null; ResultSet rs = null;
        try{
            ctx = new InitialContext();
            DataSource ds = (DataSource) ctx.lookup("java:/comp/env/prod-jdbc/ds-1");
            con = ds.getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery("SELECT nome FROM Customers");
            while(rs.next()) {
                System.out.println(rs.getString("name"));
            }
        }
        catch(NamingException | SQLException e){
            e.printStackTrace();
        } 
        finally{
            try {
                rs.close(); stmt.close(); con.close(); ctx.close();
            } catch (SQLException e) {
                System.out.println("Exception in closing DB resources");
            } catch (NamingException e) {
                System.out.println("Exception in closing Context");
            }
        }
    } // contextInitialized
} // ConnectionTester

我以这种方式设置了MySQL权限(我还需要允许“dbuser”的外部访问,因为我有一个连接到这个MySQL数据库的外部客户端):

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'veryStrongPwd';
CREATE USER 'dbuser'@'localhost' IDENTIFIED BY 'dbUserPwd!';
GRANT ALL PRIVILEGES ON *.* TO 'dbuser'@'localhost' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO 'dbuser'@'%' IDENTIFIED BY 'dbUserPwd!' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Tomcat没有配置任何特定的配置或资源,它只是在文件夹中解压缩的v9.0.12.

我试图在context.xml中放入“root”和“dbuser”凭据,但是当我启动Tomcat时,我遇到以下问题:

ConnectionPool.init Unable to create initial connections of pool.
 java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:873)
        at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1710)
        at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226)
...

抛出那些exeptions后,它打印记录集,但为什么它需要root登录,即使在context.xml中我设置了dbuser凭据?

我在*中读过这里的搜索,我读过我要检查mysql.user表,如果我运行:

SELECT user, host, plugin, authentication_string FROM mysql.user;

我得到这个(“插件”列的每个记录都有“mysql_native_password”值):

如果我尝试从shell登录MySQL服务器:

mysql -u root (or dbuser) -p

我可以成功登录.

编辑:我发现从context.xml(为开发环境制作的那个)删除了第二个“Resource”节点,问题消失了,但我仍然不明白为什么会发生这种情况,因为在查找中我选择了prod资源(ctx.lookup( “Java的:/ comp / env的/ PROD-JDBC / DS-1”)).

我错过了什么?提前致谢

解决方法:

在context.xml中,您拥有root用户密码.在MySQL脚本中,您已将root用户密码设置为veryStrongPwd.

如果你的问题更多的是为什么你得到错误,即使你不使用资源 – 你将连接池的最小大小设置为3.所以Tomcat将创建连接池,并尝试添加3个连接到它在启动时.也许如果你将minIdle设置为0,它将按照你想要的方式工作.

UPDATE

还有另一个设置 – initialSize默认为10.将其设置为0应该会阻止Tomcat尝试在启动时使用该DataSource.

上一篇:JAVA实训7-常见异常


下一篇:sqldatetime溢出异常c#.NET