It seems #csrf_exempt doesn't work anymore from Django 1.4, I have been trying to use different solutions which I have found on StackOverflow, such as removing a few middleware classes or adding a custom one, but I can't stop getting "CSRF Verification Failed". I just need to disable it for a login view that I am using with my Android app.
If you're using Class Based Views, you could use django-braces which has a Mixin for that:
class UpdateProfileView(CsrfExemptMixin, LoginRequiredMixin, UpdateView):
model = Profile
according to this the decorator #csrf_exempt should still work
maybe your login page is hitting multiple urls and you didn't exempt all of them?
Related
I am building an application with a Django Rest backend, and a VueJS front end and am working through authorization and authentication. I have the authentication working well, but am a bit stuck on letting the front end (VueJS) know what the user has authorization to do in terms of Add/Change/View/Delete for a model. For example, if a user cannot add a customer, I don't want to show the 'Add Customer button'.
Working through the Django docs, and solutions on StackOverflow, I believe the simplest way is to send the user's permissions from Django to VueJS.
The 'best'/'simplest' way I can see to get the permissions is with the following:
userModel = User.objects.get(request.user)
return User.get_all_permissions(userModel)
Where I am stuck is exactly where to put this logic and how to serialize it. Does the above belong in the View, Serializer, other? Up until now, I have only been working with Models (ModelSerializers and ModelViews), but I don't believe this falls into this category.
Thanks in advance...
You should add this logic to views, because the views are used to implement these kinds of logic.
Actually, you don't want to use serializers here, because of the response of .get_all_permissions() method is already in serialized form
Apart from that, your provided code is not good (it's clearly bad). It should be as below,
return request.user.get_all_permissions()
because, you'll get current logged-in user's instance through request.user, to get his/her permissions, you all need to call the get_all_permissions() method
Example
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
#permission_classes(IsAuthenticated, )
#api_view()
def my_view(request):
logged_in_user = request.user
return Response(data=logged_in_user.get_all_permissions())
I'm using django-rest-framework and implement very simple post CRUD API.
But the problem is UpdateView and DeleteView occurs csrf error
"detail": "CSRF Failed: CSRF token missing or incorrect."
Strange thing is CreateView doens't require csrf and works very well.
Here is my view and serializer
views.py
class PostEditAPIView(RetrieveUpdateAPIView):
"""
http://example.com/posts/1/edit
"""
queryset = Post.objects.all()
serializer_class = PostUpdateSerializer
lookup_url_kwarg = 'post_id'
serializer.py
class PostUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = [
"title",
"content",
]
I think this is enough for source code.
After clicked PUT button,
How can I deal with csrf in API?
I didn't touch any SETTINGS about Rest-framework
One of the solutions I like to use is to forcefully remove any and all kinds of CSRF checks by instructing Django to do so in the middlewares level.
To do this, create a new middleware class which contains the code to disable CSRF checks, and add the middle ware to your existing list of middlewares to run. Make sure you add your custom middleware AFTER the default authentication middleware being used by Django (Order of middlewares in settings matters).
class CSRFDisablerMiddleware(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
Beware I safely use this method since my app is protected using other means of authentication. I am not sure about how you would go about solving this problem if your project needs CSRF authentication in certain areas and not in others. The method described above will disable CSRF authentication throughout your entire Django project.
I have a django application and I want to add my own auth validation and check if the user is expired (check the expiration date from some of my models). I want to raise a ValidationError in the login page with appropriate message if user is expired. What's the best way to do that?
Thanks, Alex
If you REALLY want to do your own custom authentication, you should read custom backends in the Django Documentation.
You probably don't want to do your own though. It sucks. Really. Unless there is a really really good reason, you should avoid your own authentication. The main reason being, that many django apps stop working if you don't use the built in User model. If you need to authenticate against an existing source, that's a valid reason for creating your own backend. But there are pitfalls, and you still probably want to use the built in User model for your custom backend.
You should tell us why you want to do your own custom authentication, and perhaps we can help you achieve your requirement, without writing a custom backend.
Edit
Ok, I think I understand what you mean now. What (I think) you want, is a custom authentication form. We currently use custom form (though we have a different unavoidable backend), so you should be able to use the following quite easily.
from django.contrib.auth.forms import AuthenticationForm
from django import forms
from myproject.myapp.models import MyClass
class CustomAuthForm(AuthenticationForm):
def clean(self):
cleaned_data = super(CustomAuthForm, self).clean()
user = self.user_cache # set by super class
if user.my_class.expired:
raise forms.ValidationError('This User has Expired!')
return cleaned_data
Then, to use this custom authentication form, you need a URL in your urls.py:
from myproject.myapp.forms import CustomAuthForm
url(r'^login/$', 'django.contrib.auth.views.login', name='login',
kwargs={'template_name':'youproject/login.html', 'authentication_form':CustomAuthForm}),
I see now that your question originally stated you wanted custom validation, not authentication. My apology for not reading your question correctly.
I am trying to create a simple, html-only facebook app for a client's fb page. I would like to use django's flatpages so that the client and his staff can change the content of the app through the django admin of their site. The problem is that Django returns a 403 "CSRF verification failed. Request aborted." error when facebook attempts to send its own POST info and access the url of the app.
I already know about the #csrf_exempt decorator, but I am not sure how I would apply it to the flatpage view, as it is within the django.contrib code. Furthermore I would only want to disable csrf protection when the view is asked to call a specific facebook.html template (not not the default.html template). If there happened to be a {% crsf_exempt %} template tag for example, that would be perfect.
Can anyone think of a way to resolve this problem? Or maybe I should give up on the idea of using the django-flatpages to serve the facebook app?
Try using this decorator on your views that are called facebook:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
this will disable csrf protection on that view.
Does this help?
I ran into the exact same problem as you. I wanted to diable csrf for flatpages (but not for the rest of the site) and ended up with the following middleware:
class DisableCSRFOnFlatPages(object):
def process_request(self, request):
try:
FlatPage.objects.get(url=request.META.get('PATH_INFO'))
setattr(request, '_dont_enforce_csrf_checks', True)
except FlatPage.DoesNotExist:
return
Add it to your settings and it should disable the csrf check whenever there's a flatpage.
The django csrf middleware can't be disabled. I've commented it out from my Middleware of my project but my logins are failing due to missing CSRF issues. I'm working from the Django trunk. How can CSRF cause issues if it is not enabled in middleware?
I have to disable it because there are lots of POST requests on my site that CSRF just breaks. Any feedback on how I can completely disable CSRF in a django trunk project?
The "new' CSRF framework from Django's trunk is also breaking an external site that is coming in and doing a POST on a URL I'm giving them (this is part of a restful API.) I can't disable the CSRF framework as I said earlier, how can I fix this?
Yes, Django csrf framework can be disabled.
To manually exclude a view function from being handled by any CSRF middleware, you can use the csrf_exempt decorator, found in the django.views.decorators.csrf module. For example: (see doc)
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view:
return Httpresponse("hello world")
..and then remove {% csrf_token %} inside the forms from your template,or leave other things unchanged if you have not included it in your forms.
You can disable this in middleware.
In your settings.py add a line to MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
Create a disable.py in myapp with the following
class DisableCSRF(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
Basically if you set the _dont_enforce_csrf_checks in your request, you should be ok.
See answers below this for a better solution. Since I wrote this, a lot has changed. There are now better ways to disable CSRF.
I feel your pain. It's not acceptable for a framework to change such fundamental functionality. Even if I want to start using this from now on, I have legacy sites on the same machine sharing a copy of django. Changes like this should require major version number revisions. 1.x --> 2.x.
Anyway, to fix it I just commented it out and have stopped updating Django as often.
File: django/middleware/csrf.py
Around line 160:
# check incoming token
# request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
# if request_csrf_token != csrf_token:
# if cookie_is_new:
# # probably a problem setting the CSRF cookie
# return reject("CSRF cookie not set.")
# else:
# return reject("CSRF token missing or incorrect.")
In general, you shouldn't be disabling CSRF protection, since doing so opens up security holes. If you insist, though…
A new way of doing CSRF protection landed in trunk just recently. Is your site by chance still configured to do it the old way? Here are the docs for The New Way™ and here are the docs for The Old Way™.
I simply tried removing the references to csrf middleware classes from my settings.py, it worked. Not sure if this is acceptable. Any comments?
Below two lines were removed -
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware',
my django version is 1.11. the middleware should be like this:
from django.utils.deprecation import MiddlewareMixin
class DisableCSRF(MiddlewareMixin):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)