Access denied for MySQL user in Django

1,168 views
Skip to first unread message

Galil

unread,
Jan 14, 2016, 8:27:27 AM1/14/16
to Django users

I have created a Django app and which uses MySQL. The settings.py file in the database sections is:

DATABASES = {
    'cdraccess': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ.get('CDR_DB_NAME', 'portal2'),
        'USER': os.environ.get('CDR_DB_USER', 'cdraccess'),
        'HOST': os.environ.get('CDR_DB_HOST', '127.0.0.1'),
        'CONN_MAX_AGE': 0,
        'PASSWORD': os.environ.get('CDR_DB_PASSWORD', ''),
    },
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
    }
}

I run the app like:

CDR_DB_PASSWORD='password' CDR_DB_HOST='host_name' ./manage.py runserver

but I get the following error:

Access denied for user 'cdraccess'@'host_ip_here' (using password: NO)")

I tried to access the database from terminal, like:

   $ mysql --host=[host_name] --user=cdraccess -p portal2

and worked fine.

What is going wrong in here? And what does this "(using password: NO)" mean?


Fred Stluka

unread,
Jan 14, 2016, 12:50:21 PM1/14/16
to django...@googlegroups.com
Galil,

I had a problem like this a couple years ago, and the solution
was to delete the anonymous MySQL guest user as:

mysql> use mysql;
mysql> delete from user where host='localhost' and 'user='';
mysql> flush privileges;

I'm not sure why Django 1.4 was trying to connect as the guest
user when it had a username and password that it was
supposed to be using, but for some reason it was.  Deleting
the guest user from MySQL fixed it for me, and is a good idea
for security reasons anyhow.

--Fred
Fred Stluka -- mailto:fr...@bristle.com -- http://bristle.com/~fred/
Bristle Software, Inc -- http://bristle.com -- Glad to be of service!
Open Source: Without walls and fences, we need no Windows or Gates.
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/e1c26a0d-a509-46eb-b496-f7f09161e606%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Galil

unread,
Jan 15, 2016, 11:20:04 AM1/15/16
to Django users
Hi Fred,

The user cdraccess is not the root user and it does not have the rights to access table 'user'. I deleted the guest user as root but nothing changes. The problem was not fixed.


On Thursday, 14 January 2016 17:50:21 UTC, Fred Stluka wrote:
Galil,

I had a problem like this a couple years ago, and the solution
was to delete the anonymous MySQL guest user as:

mysql> use mysql;
mysql> delete from user where host='localhost' and 'user='';
mysql> flush privileges;

I'm not sure why Django 1.4 was trying to connect as the guest
user when it had a username and password that it was
supposed to be using, but for some reason it was.  Deleting
the guest user from MySQL fixed it for me, and is a good idea
for security reasons anyhow.

Sergiy Khohlov

unread,
Jan 18, 2016, 2:39:52 AM1/18/16
to django-users

Using password no. Have you set notempty password with creating table permission?

15 січ. 2016 18:20 "Galil" <il...@ajenta.net> пише:

Fred Stluka

unread,
Jan 19, 2016, 1:01:18 PM1/19/16
to django...@googlegroups.com
Galil,

Try this also:

mysql> use mysql;
mysql> delete from user where host='%' and 'user='';
mysql> flush privileges;

--Fred
Bristle Software, Inc -- http://bristle.com -- Glad to be of service!
Open Source: Without walls and fences, we need no Windows or Gates.

James Schneider

unread,
Jan 21, 2016, 1:06:43 PM1/21/16
to django...@googlegroups.com
On Thu, Jan 14, 2016 at 4:11 AM, Galil <il...@ajenta.net> wrote:

I have created a Django app and which uses MySQL. The settings.py file in the database sections is:

DATABASES = {
    'cdraccess': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ.get('CDR_DB_NAME', 'portal2'),
        'USER': os.environ.get('CDR_DB_USER', 'cdraccess'),
        'HOST': os.environ.get('CDR_DB_HOST', '127.0.0.1'),
        'CONN_MAX_AGE': 0,
        'PASSWORD': os.environ.get('CDR_DB_PASSWORD', ''),
    },
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
    }
}

I run the app like:

CDR_DB_PASSWORD='password' CDR_DB_HOST='host_name' ./manage.py runserver

but I get the following error:

Access denied for user 'cdraccess'@'host_ip_here' (using password: NO)")



This error message comes up when attempting to log in to MySQL only using a user name, and not providing a password. It is a valid way to log in, but if the resourced/DB you are using has a password tied to it, then you'll get a message like this. 



 

I tried to access the database from terminal, like:

   $ mysql --host=[host_name] --user=cdraccess -p portal2


You can replicate the error by removing the -p option from this command. 

 

and worked fine.

What is going wrong in here? And what does this "(using password: NO)" mean?


My guess is that CDR_DB_PASSWORD is either not being properly populated, or not being passed correctly to your settings file. I'm guessing that PASSWORD is being populated with an empty string ("") from your .get() call, so Django is just not using it when it attempts to log into the database.

Try temporarily adding the password as the default value for .get('CDR_DB_PASSWORD', '<mypass>') and ensure things are working from there, or just set the variable directly for testing purposes.

If that works, revert it back to your current setup and add a print('DB Password: ', DATABASES['cdraccess']['PASSWORD']) (or without parentheses for Python 2), and that should print out a line in the dev server console, hopefully something like 'DB Password: <password>'. That will verify your PASSWORD field is being populated correctly. My guess is that it will print 'DB Password:' with no password from the way you describe it (since you are printing an empty string).

-James

Galil

unread,
Jan 22, 2016, 10:06:43 AM1/22/16
to Django users
That was helpful James, we are nearly there.

You were right the output was "DB Password:", with an empty string. I added my password as default value like:

        'PASSWORD': os.environ.get('CDR_DB_PASSWORD', 'my_password_here'),
 but there is something really strange happening.

When I use the default localhost IP as HOST I get the following error:

(1045, u"Access denied for user 'cdraccess'@'localhost' (using password: YES)")


When I use my actual host IP, either as default value within settings.py or as parameter running the command in the terminal, I get again the previous error:

Access denied for user 'cdraccess'@'host_ip_here' (using password: NO)")

 Why is that happening? Please not that the password is printed and it is correct.

James Schneider

unread,
Jan 22, 2016, 2:23:16 PM1/22/16
to django...@googlegroups.com
On Fri, Jan 22, 2016 at 7:06 AM, Galil <il...@ajenta.net> wrote:
That was helpful James, we are nearly there.

You were right the output was "DB Password:", with an empty string. I added my password as default value like:

        'PASSWORD': os.environ.get('CDR_DB_PASSWORD', 'my_password_here'),
 but there is something really strange happening.

When I use the default localhost IP as HOST I get the following error:

(1045, u"Access denied for user 'cdraccess'@'localhost' (using password: YES)")


When I use my actual host IP, either as default value within settings.py or as parameter running the command in the terminal, I get again the previous error:

Access denied for user 'cdraccess'@'host_ip_here' (using password: NO)")


Frankly, that will probably fail anyway by design. Unless you've tweaked the MySQL, most out of the box installations will only listen on 127.0.0.1/localhost, and not on any of the interfaces on the host. If you are getting the 'using password: NO' error, that means you either didn't provide a '-p' to the mysql command, or PASSWORD in the settings.py file is coming up empty, regardless of whether or not MySQL is listening on the address you've specified.
 
 Why is that happening? Please not that the password is printed and it is correct.

First things first: Get rid of the .get() calls entirely. Whatever method you are using to pass in the environment variables appears not to be working (or may be partially working and causing unexpected behavior):

    'cdraccess': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ['CDR_DB_NAME'],
        'USER': os.environ['CDR_DB_USER'],
        'HOST': os.environ['CDR_DB_HOST'],
        'CONN_MAX_AGE': 0,
        'PASSWORD': os.environ['CDR_DB_PASSWORD'],
    },

You don't want to use .get() here because you don't want a default for things like your DB password, you want it to fail loudly if these values are not provided. Otherwise it's no different than if you entered the values directly in the file (which you were doing anyway as the default arguments for .get()). We want a hard failure here if something is broken with the environment variables. This also ensures that these variables at the very least exist in our environment.

If that fails, you should see which key is missing, and can fix it accordingly.

For testing this issue specifically, we need to start eliminating causes. I would recommend not using the environment variables until we determine the connectivity issue with MySQL:
    'cdraccess': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'portal2',
        'USER': 'cdraccess',
        'HOST': '127.0.0.1',
        'CONN_MAX_AGE': 0,
        'PASSWORD': 'yourdbpass',
    },
Test using these settings. You should also throw in print() statements at the bottom of the file to print the other environment variables like we did with CDR_DB_PASSWORD, just to see what is actually being passed to your settings file. That is likely a separate issue, but may be contributing to our problems here. The above configuration with values manually specified should enlighten us as to whether or not the environment variables are giving us angst.

-James

Galil

unread,
Jan 25, 2016, 11:19:03 AM1/25/16
to Django users
I changed my settings.py file like this:

    'cdraccess': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'portal2',
        'USER': 'cdraccess',
        'HOST': '127.0.0.1',
        'CONN_MAX_AGE': 0,

        'PASSWORD': 'mydbpass',
    },

And the error message I get is:

(1045, u"Access denied for user 'cdraccess'@'localhost' (using password: YES)")

Then I changed it to:

    'cdraccess': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'portal2',
        'USER': 'cdraccess',

        'HOST': 'my_host_name',
        'CONN_MAX_AGE': 0,
        'PASSWORD': 'mydbpass',
    },

And I get the usual error message:

(1045, u"Access denied for user 'cdraccess'@'77.95.177.35' (using password: NO)")

I have print statements and everything looks correct. It is printed as it is in the settings.py file.

One thing I noticed is that the IP 77.95.177.35 is my machine's IP, NOT the host's IP. For some reason the host IP (as it is given in the settings.py file) is replaced in this error message by my machine's IP. Is that normal?

The command: mysql --host=[my_host_name] --user=cdraccess -p portal2 works fine. The host can be given as an IP or like "host_name.net". It works fine in both ways.


James Schneider

unread,
Jan 25, 2016, 1:06:48 PM1/25/16
to django...@googlegroups.com
Is the MySQL database running on the same server as the Django instance? If so, I would recommend that it only listen on localhost/127.0.0.1 (it should do this out of the box for most distributions). It's hard to tell which machine you are referring to with the abstracted names you're using.

If your client IP is showing up, that would indicate Django is running on your machine, and not the remote server. The server should have no idea what IP you are using at this stage. The IP listed in the error message indicates the source IP of the MySQL connection request.
 

The command: mysql --host=[my_host_name] --user=cdraccess -p portal2 works fine. The host can be given as an IP or like "host_name.net". It works fine in both ways.

Is this being run from the same server where you have the problematic Django instance? If the DB is running on the same server as the Django instance you're working with, changing the hostname to anything other than 'localhost' or '127.0.0.1' is only going to confuse things and add complication.

This feels like you have some wires crossed somewhere with multiple databases and Django installations with different settings.py files.

-James

James Schneider

unread,
Jan 25, 2016, 1:52:33 PM1/25/16
to django...@googlegroups.com

And I get the usual error message:

(1045, u"Access denied for user 'cdraccess'@'77.95.177.35' (using password: NO)")

I have print statements and everything looks correct. It is printed as it is in the settings.py file.

One thing I noticed is that the IP 77.95.177.35 is my machine's IP, NOT the host's IP. For some reason the host IP (as it is given in the settings.py file) is replaced in this error message by my machine's IP. Is that normal?


Another thought. Do you manage the server/MySQL instance? Have you looked at the logs for MySQL to ensure that the password is the only issue? It's possible you are getting access denied for a number of reasons, including the database not existing when Django tries to access it.

-James

 

Ivan Gruer

unread,
Oct 9, 2017, 9:12:04 AM10/9/17
to Django users
Hi,
as far as i understood cdraccess  is a DB gust user, right?

If so, from your DB admin user, grant cdraccess to access MySQL environment table 'mysql.user' as follow:
 
GRANT SELECT ON `mysql`.`user` TO 'user_gui'@'%';

To me it worked,
Ivan

Ivan Gruer

unread,
Oct 9, 2017, 9:12:04 AM10/9/17
to Django users
Hi,
as far as i understood cdraccess  is a DB gust user, right?

If so, from your DB admin user, grant cdraccess to access MySQL environment table 'mysql.user' as follow:
 
GRANT SELECT ON `mysql`.`user` TO 'cdraccess'@'%';

To me it worked,
Ivan

Reply all
Reply to author
Forward
0 new messages