如何使用REST框架JWT进行身份验证测试?

12

基于JWT的身份验证在通过移动设备和“高级 REST 客户端”发送的 POST 请求中运作良好,但是在使用 Django 测试客户端时会失败。当请求获得令牌时,客户端可以成功接收令牌,但是在使用该令牌访问受限视图时,客户端会收到以下响应:

“未提供身份验证凭据。”

测试用例:

def test_get_token(self):
        response = self.client.post("/auth/api/get_token/", {"username": "Heffalumps", "password": "Woozles"})
        self.assertEqual(response.status_code, 200, "The token should be successfully returned.")

        response_content = json.loads(response.content.decode('utf-8'))
        token = response_content["token"]

        # The following request fails
        response = self.client.post("/auth/api/authenticated/", {}, Authorization='JWT ' + token)
        response_content = json.loads(response.content.decode('utf-8'))

        self.assertEqual(response_content["authenticated"], "mooh", "The user should be able to access this endpoint.")

测试客户端发出的请求: 在此输入图片描述

受限制的视图:

class RestrictedView(APIView):
    permission_classes = (permissions.IsAuthenticated, )
    authentication_classes = (JSONWebTokenAuthentication, )

    def post(self, request):

        response_data = json.dumps({"authenticated": "mooh"})

        return HttpResponse(response_data, content_type='application/json')

这个测试用例有什么我漏掉的地方吗?

4个回答

27
好的,以下似乎解决了问题:
而不是:
response = self.client.post("/auth/api/authenticated/", {}, Authorization='JWT ' + token)

我必须写:

response = self.client.post("/auth/api/authenticated/", {}, HTTP_AUTHORIZATION='JWT {}'.format(token))

现在,Django测试客户端也可以通过身份验证了。


1
谢谢!救了我的一天。 - Omran Shagooj
我之前使用的是Django Rest API,采用了令牌认证方式。现在需要将其更改为:response = self.client.get('/api/someurl', {}, HTTP_AUTHORIZATION='Token {}'.format(self.token)) - Joris Kok

4
请注意,在创建用户时,必须使用密码的哈希版本。例如:

User(email='TestUser@email.io', password=make_password('TestPassword')))

(使用djangos密码哈希程序)

当调用/auth/api/get_token/时,必须使用清晰的密码。例如:

response = self.client.post("/auth/api/get_token/", {'email': 'TestUser@email.io', 'password': 'TestPassword'})

花了我一段时间才发现请求响应了'non_field_errors': ['Unable to log in with provided credentials.'],是因为我在创建用户时没有使用哈希程序。


1

0
创建一个基本方法:
def create_jwt_token(user) -> str:
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    payload = jwt_payload_handler(user)
    token = jwt_encode_handler(payload)
    return 'JWT ' + token

在你的测试中,像这样使用它:
@classmethod
    def setUpTestData(cls):
        cls.valid_auth_headers = {
            "HTTP_AUTHORIZATION": UserTestUtils.create_jwt_token(cls.user)
        }

def test_valid_accepted_inputs_only(self):
        response = self.client.post(
            self.url,
            {
                "name": 'NewFarmName',
                "age": 2010
            },
            **self.valid_auth_headers,
        )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接