首页 > 解决方案 > 当我为 Django Rest Framework API 测试我的 POST 路由时,即使已登录,它也会返回未经过身份验证的 401

问题描述

当我尝试为我的 Django Rest Framework API 测试我的 Create/POST 路由时,我收到了 401 的响应状态代码,错误详情告诉我ErrorDetail(string=u'Authentication credentials were not provided.', code=u'not_authenticated')。奇怪的是,当我检查 is_authenticated 时,Django 告诉我我已通过身份验证。

有谁知道可能是什么原因造成的?下面提供的所有相关代码。

# test_api.py

def authorise_user_and_test_is_authenticated(self, user_id):
    """
    Log in user and test this is successful
    """
    user = User.objects.get(pk=user_id)
    self.client.login(username=user.username, password=user.password)
    authorised_user = auth.get_user(self.client)
    return self.assertTrue(user.is_authenticated())

def test_create_project(self):
    '''
        When given valid parameters a project is created.
    '''
    user = User.objects.get(username="user_001")
    self.authorise_user_and_test_is_authenticated(user.id) # pass of authenication and auth testing to method, when tested with is_authenicated() it returns true.

    response = self.client.post('/api/user/{0}/project/create/'.format(user.id),
                                 json.dumps({"model_name": "POSTed Project",
                                             "description": "Project tested by posting",
                                             "shared_users[]": [2]
                                             }),
                                 content_type='application/json')

    self.assertEqual(response.status_code, 201)

# views.py

class MyCreateView(generics.GenericAPIView):
    pass
    serializer_class = FerronPageCreateAndUpdateSerializer

    def get_queryset(self):
        return User.objects.filter(pk=self.kwargs.get('user'))

    def post(self, request, format=None, **kwargs):
        # This dictionary is used to ensure that the last_modified_by field is always updated on post to be the current user
        print request.data
        request_data = {
            'user': request.user.id,
            'model_name': request.data['model_name'],
            'description': request.data['description'],
            'last_modified_by': request.user.id,
            'shared_users': request.data.getlist('shared_users[]', [])
        }
        serializer = FerronPageCreateAndUpdateSerializer(data=request_data)

        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

# settings.py

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
       'rest_framework.authentication.SessionAuthentication'
   ),
}

# url matcher

url(r'^user/(?P<user>\d+)/project/create/$', MyCreateView.as_view(), name='create-project')

class FerronPageCreateAndUpdateSerializer(serializers.ModelSerializer):
shared_users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all(), read_only=False)
description  = serializers.CharField(max_length=300, trim_whitespace=True, required=False, allow_blank=True)

class Meta:
    model = Project
    fields = [
      'pk',
      'user',
      'data',
      'model_name',
      'description',
      'created_at',
      'date_modified',
      'shared_users',
      'last_modified_by'

]

标签: pythondjangodjango-rest-framework

解决方案


原来问题出在方法self.client.login(username=user.username, password=user.password)内部authorise_user_and_test_is_authenticated(self, user_id)

问题是我使用的密码是我已经创建的用户实例。这意味着当我给出论点时password=user.password,我试图使用已经散列的密码登录。我需要做的是使用原始未散列的密码版本登录,例如password='openseasame'.


推荐阅读