Recently, I've started to experience an issue on my Django-based site where logins will fail with no errors reported to the user after a few days of site uptime. Already logged in sessions continue to work fine, but no new logins can happen.
The relevant info:
I'm using the normal django.contrib.auth authentication stuff
I am using PostgreSQL for the DB via the django.db.backends.postgresql_psycopg2 backend
I am running on OSX 10.6.7 with Python 2.6.1 and Django 1.3
Django is running in FastCGI mode behind nginx
My gut feeling is that there is something breaking down in the connection / socket to the DB at some point, because if I kill Django and restart it, everything works just fine again (i.e. the DB itself is definitely not overloaded and can be accessed just fine using the psql commandline tool).
Unfortunately, there is nothing in the logs about the error (well, at least nothing is being emitted via the normal Python logging module which is how I trap all my logs) and there are no errors reported to the web browser. All the client sees is that they get sent back to the login page again, as if they had just refreshed their browser.
Any help much appreciated.
Not sure if it's relevant, but my middleware classes are:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
UPDATE
After looking into the nginx access logs, I can see that the login actually works briefly then suddenly doesn't work:
"POST /accounts/login/ HTTP/1.1" 302 5 "https://myapp.com/accounts/login/?next=/orders"
"GET /orders HTTP/1.1" 301 185 "-"
"GET /orders HTTP/1.1" 302 5 "-"
"GET /accounts/login/?next=/orders HTTP/1.1" 301 185 "-"
"GET /accounts/login/?next=/orders HTTP/1.1" 200 1297 "-"
As you can see, the login works and the client is redirected to the 'next' URL (/orders), but then the third line redirects (302) the client back out to the login page, presumably because the #login_required decorator (which is applied to the /orders controller) determined that they weren't really logged in.
For comparison, this is a successful login sequence:
"POST /accounts/login/ HTTP/1.1" 302 5 "https://myapp.com/accounts/login/?next=/orders"
"GET /orders HTTP/1.1" 301 185 "-"
"GET /orders HTTP/1.1" 200 59364 "-"
And a login with the wrong password (the POST comes back with a 200 instead of a 302):
"POST /accounts/login/ HTTP/1.1" 200 1426 "https://myapp.com/accounts/login/?next=/orders"
The difference between a normal login and the broken one is that the client gets a 200 OK for /orders instead of 302 back to the login page. I have no idea how the auth middleware can allow the login and then kick the user back out immediately after. Is there a possible race condition here where the login controller hasn't been able to persist the logged-in state into the DB in time for the /orders controller to see it and allow the user to stay logged in?
Also - I have noticed that a Django restart isn't necessarily required to fix the issue - sometimes the server just miraculously starts letting clients log in again.
Sounds like your web server is using persistent connections and running out. What do the pg logs say when you can't log in?
Related
I'm new to python and django.
I've copied my production app, that another developer wrote, onto my local. It's working perfectly. When I run django admin I get the login form. But when I enter my ID and PW I get redirected to the same login form, only it's blank; I never get logged in.
The server console reads:
[26/Apr/2022 06:25:21] "POST /admin/login/?next=/admin/ HTTP/1.1" 302 0
[26/Apr/2022 06:25:21] "GET /admin/ HTTP/1.1" 302 0
[26/Apr/2022 06:25:21] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 11020
I don't understand what's needed to change or get added. Any help appreciated.
I've sorted the issue.
I commented out SESSION_COOKIE_DOMAIN from my settings.py file and that solved it.
How can I get my GraphQL API to show more query/post data in the console? I'm running a Django app that is powered by GraphQL and served via a react frontend. With regular Django paths I would see something like this in the development server:
[04/Sep/2020 11:53:08] "GET /my_app/2020/09/01/5cc4e7cc-7.png HTTP/1.1" 200 11330
But with GraphQL all I see is this:
[04/Sep/2020 11:53:18] "POST /graphql HTTP/1.1" 200 32
[04/Sep/2020 11:53:18] "POST /graphql HTTP/1.1" 200 2993
[04/Sep/2020 11:53:29] "POST /graphql HTTP/1.1" 200 11635
Any ideas?
I highly suggest checking out Silky. It's a profiling tool that can show you
the request body - that's where you'll find the graphql
speed of the response
all the DB queries sent during your request
(if you set it up) cprofiler for the request
I am using Django 1.9, Python 3, running locally on Docker (for testing)
Trying to integrate django-saml2-auth into my application.
Pretty much followed all the steps in the docs:
1) All installations were successful
2) New URLs were imported above the rest
3) Installed apps includes 'django_saml2_auth'
4) 'SAML2_AUTH' dict was placed in settings (and all attributes were mapped)
5) In the SAML2 identity provider (using OneLogin), the Single-sign-on URL and Audience URI(SP Entity ID) was set to http://127.0.0.1:8000/saml2_auth/acs/
What happens is that when I get to http://127.0.0.1:8000/admin the browser goes into an infinite redirect loop:
...
[02/May/2018 15:43:06] "GET /admin/ HTTP/1.1" 302 0
[02/May/2018 15:43:06] "GET /admin/login/?next=/admin/ HTTP/1.1" 302 0
[02/May/2018 15:43:07] "POST /saml2_auth/acs/ HTTP/1.1" 302 0
[02/May/2018 15:43:07] "GET /admin/ HTTP/1.1" 302 0
[02/May/2018 15:43:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 302 0
[02/May/2018 15:43:08] "POST /saml2_auth/acs/ HTTP/1.1" 302 0
[02/May/2018 15:43:08] "GET /admin/ HTTP/1.1" 302 0
...
When I disable django-saml2-auth I see that a staff user was created.
In the OneLogin interface I can see that I logged in successfully.
Overriding django_saml2_auth.views.signin(r), where r is a django.core.handlers.wsgi.WSGIRequest, for <WSGIRequest: GET '/admin/login/?next=/admin/'>, and in the request, the user is set to AnonymousUser, COOKIES contain sessionid and csrftoken.
I would expect that a session would start for the user that was created/fetched, and that I will get to an /admin/<whatever> page.
I will appreciate any help in debugging this, thank you!
EDIT: I was able to get it to work by removing AUTHENTICATION_BACKENDS from settings.py- I have 3 other backends that I use. It seems like they conflict with django-saml2-auth.
Is there any way to get django-saml2-auth to work with other backends?
EDIT 2: Will try to integrate django-saml2-pro-auth, which has a backend so will not conflict. I would really appreciate some insight though.
EDIT 3: back to EDIT 2, when I remove all the backends and they don't conflict, the log flow looks like that:
[04/May/2018 15:24:26] "GET /admin/ HTTP/1.1" 302 0
[04/May/2018 15:24:27] "GET /admin/login/?next=/admin/ HTTP/1.1" 302
[04/May/2018 15:26:27] "POST /saml2_auth/acs/ HTTP/1.1" 302 0
[04/May/2018 15:26:27] "GET /admin/ HTTP/1.1" 200 38398
Where the last GET does not get redirected, with 200.
Issue resolved:
After taking a deeper dive- it seems like this code is the issue:
In django_saml2_auth/views.py, acs():
if target_user.is_active:
target_user.backend = 'django.contrib.auth.backends.ModelBackend'
login(r, target_user)
else:
return HttpResponseRedirect(get_reverse([denied, 'denied', 'django_saml2_auth:denied']))
It seems like the default ModelBackend is necessary.
When other backends are used, the default is no longer used by Django, and hence the infinite loop.
If the default backend is added to the list of backends, everything works as intended.
I am curious, I run the runserver with Django, the first request is what I am working on, but how about the others? I don't provide baidu server, why does someboy request it from my temporary server?
[02/Feb/2018 12:20:05] "GET /stk/?format=json&_=1517542783567
HTTP/1.1" 200 2247 Invalid HTTP_HOST header: '1.164.39.192'. You may
need to add u'1.164.39.192' to ALLOWED_HOSTS. [02/Feb/2018 12:50:54]
"GET //wp-login.php HTTP/1.1" 400 62538 Invalid HTTP_HOST header:
'1.164.39.192'. You may need to add u'1.164.39.192' to ALLOWED_HOSTS.
[02/Feb/2018 12:51:20] "GET /wp//wp-login.php HTTP/1.1" 400 62571
Invalid HTTP_HOST header: 'www.baidu.com'. You may need to add
u'www.baidu.com' to ALLOWED_HOSTS. [02/Feb/2018 14:15:00] "GET
http://www.baidu.com/cache/global/img/gs.gif HTTP/1.1" 400 62677
if a request comes(like search engine crawlers etc.) with the HTTP host header which is not present in your ALLOWED_HOSTS setting Django create log like yours.
Before they hit Django app you can kill these request. For solutions check this
When I start the Django server, I can see the logs in the terminal:
[31/Jan/2015 14:06:27] "GET / HTTP/1.1" 200 30697
What does the last number signify?
('30697' in this example)
This is the size of the response (in bytes).