WSGIRequest object has no attribute user on middleware function - django

I have the following middleware function:
class LastVisitMiddleware(object):
def process_response(self, request, response):
if request.user.is_authenticated():
customer = get_customer(request)
Customer.objects.filter(pk=customer.pk).update(last_visit=now())
return response
My middleware entries look like this:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'my.middleware.LastVisitMiddleware',
)
My url looks like:
url(r'^dashboard/$', views.dashboard, name='dashboard'),
When I go to urls that have a forward slash the page loads normally. When I omit the forward slash I get the error:
WSGIRequest object has no attribute user
When I remove the middleware I have no issues whether I use the forward slash or not.
How can I prevent from throwing this error with or without a forward slash?

I know that Django redirects any urls without the trailing /, so /home to /home/, but I am not sure when Django does this redirection (apparently after it has run the middleware?). One way to get around this is to check if the user object has been set;
if hasattr(request, 'user') and request.user.is_authenticated():
This should fix your problem.

During the response phases (process_response() and process_exception() middleware), the classes are applied in reverse order, from the bottom up
similar question:
Django: WSGIRequest' object has no attribute 'user' on some pages?

Related

Django csrf token not refreshed after first login

I have hosted a website at http://cognezic-dev.ap-south-1.elasticbeanstalk.com/login/. On closer inspection, the form has the same csrf token across page refreshes and browsers, which I suspect to be the cause of the issue,this works fine on the local django server.Dont know where this is being cached. I have added CSRF Middleware in the settings.py too.
You can use the test credentials as username bismeet and password bis12345 for testing.
I have also tried creating a custom middleware as follows:
from django.middleware.csrf import rotate_token, CsrfViewMiddleware
from django.utils.deprecation import MiddlewareMixin
class CSRFRefresh(CsrfViewMiddleware,MiddlewareMixin):
def process_response(self, request, response):
print("Custom MiddleWare called")
rotate_token(request)
return response
But it still fails.
My settings.py with custom middleware contains:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'solvesto.middleware.csrf_refresh.CSRFRefresh'
]
If not using the custom middleware,I use:
'django.middleware.csrf.CsrfViewMiddleware'
instead of
'solvesto.middleware.csrf_refresh.CSRFRefresh'
The only last resort I see to make this work is to remove csrf altogether,which is of course,bad for security.
I removed the csrf security,no other solution,works now.

middleware does an infinite redirect

I've already read this but the answer doesnt fit my needs.
I've made this very simple middleware:
class RedirectIfUserIsNotActiveMiddleware(object):
"""
Middleware to redirect if account is disabled
"""
#staticmethod
def process_request(request):
if not request.user.is_active:
try:
# test to see if not already on the right url:
a = resolve(request.path)
if a.url_name != settings.URL_REDIRECT_USER_NOT_ACTIVE:
return HttpResponseRedirect(
reverse_lazy(settings.URL_REDIRECT_USER_NOT_ACTIVE))
# request.path do a 404 if URL unknown -> do nothing :
except Resolver404:
pass
And I've added this here:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'third_party.hqf_middleware.RedirectIfUserIsNotActiveMiddleware',
)
But when the account is disabled I get an infinite loop with the message on the webbrowser: "mywebsite.com redirected you too many times.".
In my settings I have this:
URL_REDIRECT_USER_NOT_ACTIVE = 'my_home_profile_account_desactivated'
And the URL I'm trying to get is always (even each time step by step) /en/my-home/profile/edit
What am I missing?
It looks as if the my_home_profile_account_desactivated view is redirecting to your login page, and then the middleware redirects back to my_home_profile_account_desactivated, creating a redirect loop.
You should be able to break the authentication loop by changing the middleware so that you only redirect users that are authenticated and inactive.
#staticmethod
def process_request(request):
if request.user.is_authenticated() and not request.user.is_active:
...

Django 'WSGIRequest' object has no attribute 'set_cookie'

I keep on getting this exception when I do request.set_cookie() in the process_view of a custom middleware class. Here is the order of middleware classes in my settings.py:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'website.middleware.UserLastActiveMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
)
To start off with, set_cookie() is a method of HttpResponse, not HttpRequest, as you set cookies in your response to a requests.
Secondly, your middleware should come after AuthenticationMiddleware, since presumably it has to do with users.
You should set_cookie() call from response object.
Example:
def process_response(self, request, response):
...
response.set_cookie('user_agreement', user_agreement, domain='.mysite.com')
return response
You can take a look at this question: Django: WSGIRequest' object has no attribute 'user' on some pages?
This problem usually occurs when you do not add the trailing slash because then a redirect is done to the url containing a trailing slash

how to define a custom wsgi middleware for django

I want to write a custom wsgi middleware, which is called on every incoming request. It checks the url, and if the user is authenticated and allows the request to proceed or rejects it.
What is the best way to add wsgi middleware in django ?
Why do you want to do this as a WSGI middleware, specifically? Django doesn't operate particularly well with those - there was some work a few years ago to try and harmonize Django middleware with WSGI middleware, but it didn't really get anywhere.
Django has its own version of middleware, which is very well documented, and your request could be done in about three lines.
You do not need a wsgi middleware here and can easily use django middleware.
some_app/middleware.py
from django.http import HttpResponseForbidden
class AuthenticateMiddleware(object):
def process_request(self, request):
#do something with request.path
if request.user.is_authenticated():
#can do something or just pass
#but do not return a response from here
else:
#return a response from here so that view doesn't get called
return HttpResponseForbidden()
process_request() of any middleware is called before the view is processed. If you return an instance of HttpResponse from this method then the view will not be called. Since HttpResponseForbidden is a subclass of HttpResponse, so the view will not be called if the user is not authenticated.
You need to add this custom middleware to MIDDLEWARE_CLASSES.
settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'some_app.middleware.AuthenticationMiddleware',
)

django post request data caching

hi have a template with a form and many inputs that pass some data trough a POST request to a view, that process them and send the result to another template. in the final template, if i use the browser back button to jump to the first view, i can see again old data. i refresh the page and i insert new data, i submit again but some old data remain when i see the final view. the problem remain even if i restart the debug server. how can i prevent it? it seems that there's some data-caching that i can solve only flushing browser cache. this is the view code: http://dpaste.com/640956/ and the first template code: http://dpaste.com/640960/
any idea?
tnx - luke
Is not django who populate form. Is cache navigator. You should switch off cache navigator. I use a custom middleware to do this:
from django.http import HttpResponse
class NoCacheMiddleware(object):
def process_response(self, request, response):
response['Pragma'] = 'no-cache'
response['Cache-Control'] = 'no-cache must-revalidate proxy-revalidate no-store'
return response
Remember to add middleware on settings.py:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'ghap.utils.middleware.NoCacheMiddleware',
)
Maybe autocomplete="off" in the form tag can help you.
https://developer.mozilla.org/en/How_to_Turn_Off_Form_Autocompletion