Нужны советы по обеспечению безопасности частного REST API, написанного на python-flask - PullRequest
15 голосов
/ 29 августа 2011

В настоящее время я пишу API отдыха на python с микросхемой Flask. Это частный API, который работает с пользовательскими данными . Я планирую использовать этот API для создания веб-приложений и приложений для Android.

Сейчас я использую дайджест-аутентификацию для защиты личных данных пользователя. Например, если вы хотите опубликовать данные на моем сервисе с пользователем bob, вы отправляете запрос на myapi / story / create и предоставляете учетные данные bob с шаблоном дайджеста.

Я знаю, что это не очень хорошее решение, потому что:
-Дайджест аутентификации не безопасен
-Клиент не аутентифицирован (Как защитить запросы, не связанные с текущим пользователем, например, создать нового пользователя?)

Я много читал о oAuth, но трехсторонняя аутентификация кажется излишней, потому что я не планирую открывать свой API для третьих лиц.
Двусторонний oAuth не подходит, поскольку он обеспечивает аутентификацию только для клиентов, а не для пользователей.
Другая проблема с oAuth заключается в том, что я не нашел исчерпывающего руководства по его реализации на Python. Я нашел библиотеку python-oauth2 , но я не понимаю пример сервера и не могу найти дополнительную документацию. Кроме того, похоже, что многие аспекты oAuth не рассматриваются в этом примере.

Итак, мои вопросы:

  1. Существует ли альтернативная схема (не oAuth) для аутентификации клиента и пользователя с разумным уровнем безопасности?
  2. Если oAuth - лучшее решение:
    • Как пропустить процесс авторизации (поскольку пользователям не нужно будет авторизовать сторонних клиентов)?
    • Есть ли подробная документация для python-oauth2 или для любой другой библиотеки Python?

Любая помощь или совет будут оценены.

Ответы [ 3 ]

8 голосов
/ 04 июня 2012

Простой ответ - открыть ваш API только через HTTPS, а затем использовать базовую аутентификацию HTTP. Я не думаю, что есть какая-то причина беспокоиться о дайджесте. Обычная аутентификация небезопасна, но отправляется с каждым запросом, поэтому вам не нужно беспокоиться о том, что ваша аутентификация устарела или что-то в этом роде. Туннелируя его по HTTPS, вы получаете безопасное соединение.

Если вы хотите аутентифицировать клиента, вы можете использовать SSL-сертификаты клиента. Тем не менее, в целом довольно сложно действительно заблокировать клиент от злонамеренных пользователей, поэтому я хотел бы рассмотреть возможность сделать функции регистрации открытыми и защитить себя от DOS и т. Д. С помощью внеполосной проверки учетной записи.

4 голосов
/ 29 августа 2011

Вы уже рассматривали возможность использования базовой аутентификации?

Я еще не использовал упомянутую вами платформу, но я использовал базовую аутентификацию для защиты некоторых URL-адресов в приложении на основе web.py и работала нормально.

По сути, вы можете использоватьтокен в base64, который на самом деле является стандартным http-заголовком.

Может быть, этот пример поможет вам:

class Login:

    def GET(self):
        auth = web.ctx.env.get('HTTP_AUTHORIZATION')
        authreq = False
        if auth is None:
            authreq = True
        else:
            auth = re.sub('^Basic ','',auth)
            username,password = base64.decodestring(auth).split(':')
            if (username,password) in settings.allowed:
                raise web.seeother('/eai')
            else:
                authreq = True
        if authreq:
            web.header('WWW-Authenticate','Basic realm="Auth example"')
            web.ctx.status = '401 Unauthorized'
            return
0 голосов
/ 26 января 2013

Если вы заинтересованы в базовой аутентификации, вот быстрый атрибут, который вы можете использовать для украшения ваших обработчиков http://www.varunpant.com/posts/basic-authentication-in-web-py-via-attribute. Этот пример в основном написан в контексте web.py, но я думаю, его можно легко настроить.

def check_auth(username, password): 
    return username == 'username' and password == 'password'


def requires_auth(f):
    @wraps(f)     
    def decorated(*args, **kwargs):        
        auth = web.ctx.env['HTTP_AUTHORIZATION'] if 'HTTP_AUTHORIZATION' in  web.ctx.env else None
        if auth:
            auth = re.sub('^Basic ', '', auth)
            username, password = base64.decodestring(auth).split(':')
        if not auth or not check_auth(username, password):
            web.header('WWW-Authenticate', 'Basic realm="admin"')
            web.ctx.status = '401 Unauthorized'
            return 

        return f(*args, **kwargs)

    return decorated
...