2013-05-11 117 views
8

我有以下代码:CSRF豁免失败 - APIView CSRF Django的REST框架

问题是,当我试图访问用户登录/我得到一个错误:“:未设置CSRF饼干CSRF失败。”

我该怎么办?

我正在使用django rest框架。

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 

回答

14

我假设你使用django rest框架SessionBackend。这个后端做了implicit CSRF check

您可以通过避免这种情况:

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) 

并且在视图

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("/") 
9

其实它设置为authentication_classes,更好的方法来禁用内SessionAuthentication CSRF检查:

from rest_framework.authentication import SessionAuthentication as OriginalSessionAuthentication 

class SessionAuthentication(OriginalSessionAuthentication): 
    def enforce_csrf(self, request): 
     return 
2

解决此问题的最简单方法LEM:

对于有在DRF see drf auth

BasicAuthentication

SessionAuthentication(默认)认证两种方式

SessionAuthentication具有强制CSRF检查,但BasicAuthentication没有。 所以我的方式是在我的视图中使用BasicAuthentication而不是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({})