使用Django REST和OAuth2在测试脚本中获得403响应

时间:2015-08-31 20:04:44

标签: python django oauth-2.0 django-rest-framework

我的测试脚本中有403响应,它使用Django REST和OAuth2。我正在使用force_authenticate。

在urls.py中:

urlpatterns = [
    url(r'^user-id/$', views.UserIDView.as_view(), name='user-id'),
    ...

在views.py中:

from oauth2_provider.ext.rest_framework import TokenHasReadWriteScope

class StdPerm(TokenHasReadWriteScope):
    pass

StdPermClasses = (IsAuthenticated, StdPerm)

class UserIDView(APIView):
    permission_classes = StdPermClasses
    renderer_classes = (JSONRenderer,)
    def get(self, request, format=None):
        return Response({'id': request.user.id})

在tests.py中:

from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from rest_framework import status
from rest_framework.test import APITestCase

class CreateUserTest(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user('daniel', 'daniel@test.com',
            password='daniel')
        self.user.save()
    def test_get_user_id(self):
        self.client.login(username='daniel', password='daniel')
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('user-id'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

通常我使用卷曲没问题:

curl -X GET "http://127.0.0.1:8000/user-id/" -H "Authorization: Bearer b3SlzXlpRSxURyh2BltwdHmhrlqNyt"

更新我在test_get_user_id中更改了一些行:

    token = Token.objects.create(user=self.user)
    self.client.force_authenticate(user=self.user, token=token)

现在我收到了错误:

assert False, ('TokenHasScope requires either the' AssertionError:     
TokenHasScope requires either the`oauth2_provider.rest_framework
.OAuth2Authentication` authentication class to be used.

2 个答案:

答案 0 :(得分:2)

我找到了解决这个问题的方法。基本上我的代码缺少两件事,即OAuth2应用程序记录和特定于OAuth2的访问令牌。我在setUp中添加了以下内容:

app = Application(
    client_type='confidential',
    authorization_grant_type='password',
    name='MyAppTest',
    user_id=1
)
app.save()

...用于生成合适的访问令牌:

app = Application.objects.get(name='MyAppTest')
token = generate_token()
expires = now() + timedelta(seconds=oauth2_settings. \
    ACCESS_TOKEN_EXPIRE_SECONDS)
scope = 'read write'
access_token = AccessToken.objects.create(
    user=self.user,
    application=app,
    expires=expires,
    token=token,
    scope=scope
)

...然后使用令牌:

self.client.force_authenticate(user=self.user, token=access_token)

导入部分最终结束:

from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from oauth2_provider.settings import oauth2_settings
from oauthlib.common import generate_token
from oauth2_provider.models import AccessToken, Application
from django.utils.timezone import now, timedelta

答案 1 :(得分:0)

这对我有用

from oauth2_provider.settings import oauth2_settings
from oauth2_provider.models import get_access_token_model, 
get_application_model
from django.contrib.auth import get_user_model
from django.utils import timezone
from rest_framework.test import APITestCase

Application = get_application_model()
AccessToken = get_access_token_model()
UserModel = get_user_model()

class Test_mytest(APITestCase):

    def setUp(self):

        oauth2_settings._SCOPES = ["read", "write", "scope1", "scope2", "resource1"]

        self.test_user = UserModel.objects.create_user("test_user", "test@example.com", "123456")

        self.application = Application.objects.create(
                                                name="Test Application",
                                                redirect_uris="http://localhost http://example.com http://example.org",
                                                user=self.test_user,
                                                client_type=Application.CLIENT_CONFIDENTIAL,
                                                authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE,
                                            )

        self.access_token = AccessToken.objects.create(
                                                    user=self.test_user,
                                                    scope="read write",
                                                    expires=timezone.now() + timezone.timedelta(seconds=300),
                                                    token="secret-access-token-key",
                                                    application=self.application
                                                )
        # read or write as per your choice
        self.access_token.scope = "read"
        self.access_token.save()

        # correct token and correct scope
        self.auth =  "Bearer {0}".format(self.access_token.token)

    def test_success_response(self):

        url = reverse('my_url',)

        # Obtaining the POST response for the input data
        response = self.client.get(url, HTTP_AUTHORIZATION=self.auth)

        # checking wether the response is success
        self.assertEqual(response.status_code, status.HTTP_200_OK)

现在一切都会按预期工作。感谢