299

I try to connect MySQL database with Java using connector 8.0.11. Everything seems to be OK, but I get this exception:

Exception in thread "main" java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed at
     com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:108) at 
     com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95) at
     com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at     
     com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:862) at 
     com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:444) at
     com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:230) at
     com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:226) at
     com.mysql.cj.jdbc.MysqlDataSource.getConnection(MysqlDataSource.java:438) at
     com.mysql.cj.jdbc.MysqlDataSource.getConnection(MysqlDataSource.java:146) at
     com.mysql.cj.jdbc.MysqlDataSource.getConnection(MysqlDataSource.java:119) at
     ConnectionManager.getConnection(ConnectionManager.java:28) at
     Main.main(Main.java:8)
 

Here is my Connection Manager class:

public class ConnectionManager {

    public static final String serverTimeZone = "UTC";
    public static final String serverName = "localhost";
    public static final String databaseName ="biblioteka";
    public static final int portNumber = 3306;
    public static final String user = "anyroot";
    public static final String password = "anyroot";
    
    public static Connection getConnection() throws SQLException {
    
        MysqlDataSource dataSource = new MysqlDataSource();
    
        dataSource.setUseSSL( false );
        dataSource.setServerTimezone( serverTimeZone );
        dataSource.setServerName( serverName );
        dataSource.setDatabaseName( databaseName );
        dataSource.setPortNumber( portNumber );
        dataSource.setUser( user );
        dataSource.setPassword( password );
        
        return dataSource.getConnection();
    }
}
informatik01
  • 15,636
  • 10
  • 72
  • 102
danny
  • 3,117
  • 2
  • 7
  • 9

22 Answers22

544

You should add client option to your mysql-connector allowPublicKeyRetrieval=true to allow the client to automatically request the public key from the server. Note that allowPublicKeyRetrieval=True could allow a malicious proxy to perform a MITM attack to get the plaintext password, so it is False by default and must be explicitly enabled.

https://mysql-net.github.io/MySqlConnector/connection-options/

you could also try adding useSSL=false when you use it for testing/develop purposes

example:

jdbc:mysql://localhost:3306/db?allowPublicKeyRetrieval=true&useSSL=false
Rodney
  • 2,312
  • 1
  • 13
  • 14
jtomaszk
  • 7,403
  • 2
  • 27
  • 40
  • 3
    Well, this worked for me but I am not sure how legit these options are from security perspective. – Priyank Thakkar Jun 20 '18 at 07:10
  • 47
    `useSSL=false&allowPublicKeyRetrieval=true` is what I needed only when I tried connecting from `docker_container1` to `docker_container2_mysql(where mysql is installed)` within my local host. While from my host machine to `docker_container2_mysql`, `useSSL=false` is enough. – prayagupa Jun 26 '18 at 05:02
  • 2
    allowPublicKeyRetrieval=true&useSSL=false , tank you it works – Martin Klestil Sep 02 '18 at 09:34
  • 3
    Can you explain why this is the case? – Capn Sparrow Sep 07 '18 at 04:45
  • Adding 'allowPublicKeyRetrieval=true' to my JDBC connection string solved my development system's issue after a Windows 10 update yesterday. Guess Microsoft plugged another hole, and the option should be used "for development only" in my view, where SSL is not turned on. – Alz Sep 15 '18 at 13:31
  • 14
    My problem is, it was working fine till yesterday. What could have changed overnight? – Sandeep Kumar Dec 31 '19 at 08:14
  • 8
    try removing useSSl=false from the url it worked for me – Saroj Kumar Sahoo May 02 '20 at 11:14
  • 1
    I was struggling making `dbeaver` connect to *dockerized* `mysql-8` server. `allowPublicKeyRetrieval=true` did the trick for me :+1: – ira Nov 24 '20 at 07:10
  • 1
    @SandeepKumar Same thing happened to me. Did you figure out why? And yes, I know a lot of time passed after you commented this, so I don't have high expectations :) – Stefan May 16 '21 at 15:01
264

For DBeaver users:

  1. Right click your connection, choose "Edit Connection"

  2. On the "Connection settings" screen (main screen) click on "Edit Driver Settings"

  3. Click on "Connection properties", (In recent versions it named "Driver properties")

  4. Right click the "user properties" area and choose "Add new property"

  5. Add two properties: "useSSL" and "allowPublicKeyRetrieval"

  6. Set their values to "false" and "true" by double clicking on the "value" column

AnasSafi
  • 3,608
  • 28
  • 25
Javier Aviles
  • 4,886
  • 2
  • 20
  • 25
  • 23
    For me, modifying just the "allowPublicKeyRetrieval" field under "Driver Properties" from False to True did the trick. May I ask why add the "useSSL" property and then set it to False? (I too am using DBeaver) – Sandun Dec 15 '20 at 07:07
  • On Ubuntu 16.04, I had a heck of a time figuring out how to set the value because visually it did not show anything that looked like input was expected or being recorded. I had to double click the value column and trust that it was taking input before hitting enter or clicking out of it and only then did the value I typed in show up. – Stack Underflow Feb 25 '21 at 19:34
  • 4
    Is enough set both properties in the `Driver properties` section/tab – Manuel Jordan Mar 29 '21 at 21:38
  • Trying to connect to an out-of-the-box mysql install on a docker container. Doing this made it work so I can connect to the mysql db using dbeaver. – Halfstop May 20 '21 at 04:32
  • 2
    This was the correct answer in my case when using DBeaver client – Ara Kokeba Aug 19 '21 at 01:48
  • In my case "allowPublicKeyRetrieval" properties only accept 'TRUE' (capital latter) – Istiaque Hossain Oct 28 '21 at 04:15
59

When doing this from DBeaver I had to go to "Connection settings" -> "SSL" tab and then :

  • uncheck the "Verify server certificate"
  • check the "Allow public key retrival"

This is how it looks like. DBeaver configuration

Note that this is suitable for local development only.

Michał Krzywański
  • 13,202
  • 3
  • 31
  • 53
42

Use jdbc url as :

jdbc:mysql://localhost:3306/Database_dbName?allowPublicKeyRetrieval=true&useSSL=False;

PortNo: 3306 can be different in your configuation

susan097
  • 2,960
  • 1
  • 21
  • 28
25

Alternatively to the suggested answers you could try and use mysql_native_password authentication plugin instead of caching_sha2_password authentication plugin.

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password_here'; 
Torsten Ojaperv
  • 954
  • 17
  • 22
14

I updated this parameter when I faced the issue of "public-key-retrieval-is-not-allowed" with root account.

DBeaver update this parameter

Duc Toan Pham
  • 238
  • 2
  • 6
6

I solve this issue using below configuration on spring boot framework

spring.datasource.url=jdbc:mysql://localhost:3306/db-name?useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
duyuanchao
  • 3,251
  • 23
  • 15
  • right, simplest could be your local mysql password is something different that what is configured in application.properties .. go check and change that. This was the case with mw – Rajni Gangwar Mar 09 '21 at 12:28
6

First of all, please make sure your Database server is up and running. I was getting the same error, after trying all the answers listed here I found out that my Database server was not running.

You can check the same from MySQL Workbench, or Command line using

mysql -u USERNAME -p

This sounds obvious, but many times we assume that Database server is up and running all the time, especially when we are working on our local machine, when we restart/shutdown the machine, Database server will be shutdown automatically.

6

This also can be happened due to wrong user name or password. As solutions I've added allowPublicKeyRetrieval=true&useSSL=false part but still I got error then I checked the password and it was wrong.

HashanR
  • 194
  • 2
  • 14
4

Another way, on DBeaver.

You can edit the connection of a database, go to SSL tab in connection settings. There's a checkbox "allow public key retrieval" mark it as true. That'll sove the issue.

Ravi
  • 171
  • 1
  • 10
3

The above error in my case was actually due to the wrong username and password. Solving the issue: 1. Go to the line DriverManager.getConnection("jdbc:mysql://localhost:3306/?useSSL=false", "username", "password"); The fields username and password might be wrong. Enter the username and password which you use to start your mysql client. The username is generally root and password is the string which you enter when a screen similar to this appears Startup screen of mysql

Note: The portname 3306 might be different in your case.

risingStark
  • 1,161
  • 9
  • 17
2

I found this issue frustrating because I was able to interact with the database yesterday, but after coming back this morning, I started getting this error.

I tried adding the allowPublicKeyRetrieval=true flag, but I kept getting the error.

What fixed it for me was doing Project->Clean in Eclipse and Clean on my Tomcat server. One (or both) of those fixed it.

I don't understand why, because I build my project using Maven, and have been restarting my server after each code change. Very irritating...

Cameron Hudson
  • 2,236
  • 1
  • 16
  • 30
1

This solution worked for MacOS Sierra, and running MySQL version 8.0.11. Please make sure driver you have added in your build path - "add external jar" should match up with SQL version.

String url = "jdbc:mysql://localhost:3306/syscharacterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
Stephen Rauch
  • 44,696
  • 30
  • 102
  • 125
surendrapanday
  • 394
  • 1
  • 12
1

In my case it was user error. I was using the root user with an invalid password. I am not sure why I didn't get an auth error but instead received this cryptic message.

juice
  • 1,651
  • 15
  • 11
1

Give connection URL as jdbc:mysql://localhost:3306/hb_student_tracker?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC

samit tiwary
  • 81
  • 1
  • 3
1

If you are getting the following error while connecting the mysql (either local or mysql container running the mysql):

java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed

Solution: Add the following line in your database service:

command: --default-authentication-plugin=mysql_native_password
1

Update the useSSL=true in spring boot application connection with mysql;

jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&useSSL=true&useLegacyDatetimeCode=false&serverTimezone=UTC
Bheem Singh
  • 540
  • 6
  • 12
1

In MySQL 8.0 the default authentication plugin was changed from mysql_native_password to caching_sha2_password. See https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password for more information about this change.

What that means is that in order to use caching_sha2_password the connection must do one of the following:

You have a few options:

  • ALTER the users to use the mysql_native_password plugin (like how it was doing historically and will also work with older clients / connections which don't support caching_sha2_password)
  • useSSL=true
  • useSSL=false and configure public key retrieval (this doesn't mean using allowPublicKeyRetrieval=true which would avoid the error - but defeats the objective of this extra security and is slow - it does mean using something like server-public-key-path to point to the client side copy of the public key)
Yoseph
  • 590
  • 1
  • 5
  • 8
0

I was also facing such an issue while dockerizing our existing application. The solution si to add allowPublicKeyRetrieval connection option of MySQL with a value of true to the JDBC connection string. If that is not working , try adding useSSL option to false as well .

The resultant string would look like this :

jdbc:mysql://<database server ip>:3306/databaseName?allowPublicKeyRetrieval=true&useSSL=false
Arun s
  • 607
  • 5
  • 17
0

Setting Server Time Zone to my local place, fixed the issue.


ServerTimeZone

Manohar Reddy Poreddy
  • 21,015
  • 9
  • 137
  • 125
0

My problem was in pom.xml (spring boot). My pom.xml had two dependencies entries for different databases. Make sure to keep only the MySQL dependency and remove any other database dependency entry.

Savrige
  • 2,760
  • 3
  • 28
  • 36
0
spring.datasource.url=jdbc:mysql://localhost:3306/database?createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=false

You can insert this line to your applications.properties file and this means,

  • spring.datasource.url=jdbc:mysql://localhost:3306/ This one uses mysql as the database service. I think this can changed by using relavent name and the port of your database name.
  • database?createDatabaseIfNotExist=true = use the database named database if you haven't already make a database like that, make a new one.
  • allowPublicKeyRetrieval=true = to allow the client to automatically request the public key from the server. (This part might be additional)
  • useSSL=false = This will disable SSL and also suppress the SSL errors

Furthermore, be alert about the spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect property in the same file.

Finally check whether you've added following dependency in dependencies in your pom.xml file.

<dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.23</version>
</dependency>
Damika
  • 308
  • 4
  • 13