401 при попытке аутентифицировать пользователя в Eve flask framework

Я использую потрясающую REST-framework Eve для создания CRUD API с аутентификацией JWT. Я просмотрел руководства, размещенные здесь, но получаю сообщение об ошибке 401, когда выполнение запроса POST к моим конечным точкам, для которых требуется аутентификация токена.

Я прочитал этот вопрос SO: Проблема с функцией Python Eve TokenAuth но я уверен, что токен закодирован в Base64.

Это ответ, который я получаю от сервера при выполнении запроса cURL GET:

curl -H "Authorization: <MYTOKEN>" -i http://MY_IP/users/548f6ecd64e6d12236c9576b

---- Response ----

HTTP/1.1 401 UNAUTHORIZED
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 16 Dec 2014 10:49:25 GMT
Content-Type: application/json
Content-Length: 91
Connection: keep-alive
WWW-Authenticate: Basic realm:"eve"

{"_status": "ERR", "_error": {"message": "Please provide proper credentials", "code": 401}}

Ниже мой код:

app.py

from eve import Eve
from eve.auth import TokenAuth

import jwt


class RolesAuth(TokenAuth):

    def check_auth(self, token, allowed_roles, resource, method):
        users = app.data.driver.db['users']
        # Add check of user credentials by decoding JWT
        user = users.find_one({'token': token})
        return user


def add_token(documents):
    for document in documents:
        payload = {'username': document['username']}
        document["token"] = jwt.encode(payload, 'secret')


if __name__ == '__main__':
    app = Eve(auth=RolesAuth)
    app.on_insert_users += add_token
    app.run()

settings.py

users_schema = {
    'username': {
        'type': 'string',
        'required': True,
    },
    'password': {
        'type': 'string',
        'required': True,
    },
    'email': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 200,
        'required': True,
    },
    'token': {
        'type': 'string',
    },
    'created': {
        'type': 'datetime',
    }
}

users = {
    'cache_control': '',
    'cache_expires': 0,
    'extra_response_fields': ['token'],
    'public_methods': ['POST'],
    'schema': users_schema
}

DOMAIN = {
    'users': users,
}

У меня есть токен, хранящийся в моей MongoDB для пользователя, и я делаю запрос с помощью Postman, и я m включая токен в заголовке авторизации следующим образом:

Authorization: <USERTOKEN> 

Любые мысли о том, почему это дает мне 401.

Спасибо!


person Ismailp    schedule 16.12.2014    source источник


Ответы (1)


Я проверил ваш код, но для простоты избавился от jwt.encode:

def add_token(documents):
    for document in documents:
        payload = {'username': document['username']}
        document["token"] = 'hello'

Я отправил нового пользователя в /users, а затем выполнил GET для той же конечной точки с Postman: это работает как шарм (200). Затем я провел тот же тест с curl:

curl -H "Authorization: Basic Y2lhbzo=" -i http://localhost:5000/users

Это также возвращает файл 200. Как видите, заголовок Auth закодирован (скопируйте и вставьте из предварительного просмотра запроса Postman). Просто убедитесь, что вы передаете правильный материал, возможно, установите точку останова в check_auth, чтобы проверить, что входит в него, и будет ли поиск в базе данных успешным или нет.

Надеюсь, это поможет в диагностике вашей проблемы.

PS: обратите внимание, что в curl заголовок авторизации также имеет оператор Basic перед токеном, который, похоже, отсутствует в вашем фрагменте кода.

ОБНОВЛЕНИЕ

Ради этого я также установил PyJWT и протестировал ваш код, и... он отлично работает с моей стороны. Должно быть, что-то не так с вашим запросом.

ОБНОВЛЕНИЕ 2

Одна вещь, которая может быть не столь очевидной, заключается в том, что вам все равно нужно добавить (закодированное) : к вашему заголовку аутентификации (это базовая аутентификация, и она анализирует как имя пользователя, так и пароль). Вот почему в приведенном выше примере у вас есть = в конце закодированного «привет».

person Nicola Iarocci    schedule 16.12.2014
comment
Спасибо за ответ! Итак, в основном служба аутентификации декодирует токен, который я отправляю в своем заголовке авторизации? - person Ismailp; 16.12.2014
comment
Не могли бы вы также опубликовать реализацию PyJWT, которую вы сделали. Не уверен, что делаю это правильно. Спасибо еще раз. - person Ismailp; 16.12.2014
comment
А, теперь я вижу проблему. Это решено :) Спасибо, что уделили время. - person Ismailp; 16.12.2014
comment
Я думаю, что @nicola-iarocci имел в виду использование :, а не ;, поэтому строка для кодирования будет "hello:" - person Henrique B.; 04.05.2015
comment
@ЭнрикеБ. Спасибо за указание на это. Я отредактировал ответ Николы и изменил ; на :. - person void-pointer; 27.01.2016