可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have the following code:
The problem is when I try to access user-login/ I get an error: "CSRF Failed: CSRF cookie not set."
What can I do?
I am using the django rest framework.
urls.py: url(r'^user-login/$', csrf_exempt(LoginView.as_view()), name='user-login'), views.py: class LoginView(APIView): """ List all snippets, or create a new snippet. """ def get(self, request, format=None): startups = Startup.objects.all() serializer = StartupSerializer(startups, many=True) return Response(serializer.data) def post(self, request, format=None): profile = request.POST if ('user_name' not in profile or 'email_address' not in profile or 'oauth_secret' not in profile): return Response( {'error': 'No data'}, status=status.HTTP_400_BAD_REQUEST) username = 'l' + profile['user_name'] email_address = profile['email_address'] oauth_secret = profile['oauth_secret'] password = oauth_secret
回答1:
I assume you use the django rest framework SessionBackend. This backend does a implicit CSRF check
You can avoid this by:
from rest_framework.authentication import SessionAuthentication class UnsafeSessionAuthentication(SessionAuthentication): def authenticate(self, request): http_request = request._request user = getattr(http_request, 'user', None) if not user or not user.is_active: return None return (user, None)
And set this as authentication_classes in your View
class UnsafeLogin(APIView): permission_classes = (AllowAny,) #maybe not needed in your case authentication_classes = (UnsafeSessionAuthentication,) def post(self, request, *args, **kwargs): username = request.DATA.get("u"); password = request.DATA.get("p"); user = authenticate(username=username, password=password) if user is not None: login(request, user) return redirect("/")
回答2:
Actually, better way to disable csrf check inside SessionAuthentication is:
from rest_framework.authentication import SessionAuthentication as OriginalSessionAuthentication class SessionAuthentication(OriginalSessionAuthentication): def enforce_csrf(self, request): return
回答3:
The easiest way to solve this problem:
For that there are two ways of authentication in drf see drf auth
BasicAuthentication
SessionAuthentication (default)
SessionAuthentication has a forced csrf check, but BasicAuthentication doesn't. So my way is using BasicAuthentication in my view instead of SessionAuthentication.
from rest_framework.authentication import BasicAuthentication class UserLogin(generics.CreateAPIView): permission_classes = (permissions.AllowAny,) serializer_class = UserSerializer authentication_classes = (BasicAuthentication,) def post(self, request, *args, **kwargs): return Response({})