django rest framework - аутентификация сессии против аутентификации токена, csrf - PullRequest
0 голосов
/ 13 января 2019

У меня установлен DRF с настройками по умолчанию. Мои клиенты ajax отлично работают с аутентификацией сессии. Я хочу, чтобы другой удаленный сервер использовал тот же API, что и клиенты javascript.

Мой логин-код прост:

class Login(APIView):
    def post(self, request, *args, **kwargs):

        user = authenticate(username=username, password=password)

        if user is None:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

        login(request, user)
        # ...

Проблема в том, что когда я использую клиента с другого хоста, например, python requests, я получаю ошибку CSRF. В соответствии с документами DRF, я думаю, что вместо этого я должен использовать аутентификацию токена.

Вопросы:

  1. Зачем мне нужна аутентификация токена? Cookie-файл sessionid уже является токеном, почему я не могу использовать его как для ajax-клиентов, так и для программных клиентов? Таким образом, избегайте другой отдельной таблицы БД для токенов.

  2. Поскольку я хочу использовать только аутентификацию сеанса, как применять CSRF только для клиентов ajax?

Ответы [ 2 ]

0 голосов
/ 19 января 2019
  1. Не обязательно использовать Token Authentication, просто Session Authentication подвержена атакам CSRF. Вы можете попытаться предотвратить это, используя механизмы CORS и токены CSRF, но это все еще не совсем безопасно. Честно говоря, аутентификация токена не совсем хорошо работает с браузерами, так как токен можно легко получить с помощью инструментов разработчика браузера, если вы не используете очень сложный и сложный механизм для его обработки. Проще использовать его для сторонних приложений.

  2. Хотя CSRF-атаки применимы только к браузерам (клиентам Ajax), вы не должны пытаться исключать их, потому что метод проверки, является ли запрос от клиента AJAX request.is_ajax(), зависит от того, установлен ли клиент заголовок X-Requested-With. Злоумышленник может удалить этот заголовок. Опять же, я бы посоветовал вам добавить проверку CORS, которая является методом, используемым браузерами для защиты от CSRF-атак, в дополнение к токенам CSRF Django. Обычно это делается с помощью Django-cors-headers package

А почему проверка подлинности токена не подвергается атакам csrf? Это не кажется мне более безопасным, чем сеанс. На мой взгляд, оба они используют HTTP-заголовки для передачи токена (в токене аутентификация находится в заголовке авторизации, а сессия - это cookie, который также является заголовком)

Токены отправляются с использованием заголовка Authorization (вы также можете решить использовать собственный заголовок, но это стандарт для взаимодействия), в то время как при аутентификации сеанса используются файлы cookie, которые автоматически отправляются браузером, и поэтому они восприимчивы к атакам CSRF. Для токенов клиент должен явно установить заголовок, чтобы он знал токен, в то время как злоумышленнику не нужно даже знать, что хранится в куки, так как браузер просто автоматически отправляет все, что находится в его хранилище куки для этого сайта.

0 голосов
/ 19 января 2019

Вы не должны включать защиту CSRF только для клиентов ajax - это не имеет никакого смысла. Как вы можете отличить «ajax» клиента от «нормального» клиента? Если это будет сделано, например, по некоторому параметру запроса злоумышленник может просто использовать эту «обычную» ссылку для совершения плохих действий.

Когда вы используете аутентификацию на основе токенов, злоумышленник не может просто использовать общий URL-адрес для прозрачной аутентификации вашего запроса. Вот почему только аутентификация на основе сеанса требует, чтобы в запрос был включен действительный токен CSRF.

Так что по соображениям безопасности есть 2 варианта:

  • либо использует аутентификацию на основе сеанса, но затем вам нужно отправлять cookie-файл аутентификации и токен CSRF с каждым запросом;
  • или используйте аутентификацию на основе токенов, что проще, поскольку вам нужно только предоставить аутентификационный токен, например, в качестве параметра запроса.

Могу ли я использовать аутентификацию токена, которая получает токен из стандартной таблицы django_session? просто использовать это как токен?

Теоретически вы можете достичь этого, написав некоторое специальное промежуточное программное обеспечение для аутентификации, которое будет использовать токен из параметра запроса и сопоставлять его с таблицей сеансов, но в целом это плохая идея.

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

Во-вторых, это также сделает систему более хрупкой. Поскольку сеансы и токены - это 2 совершенно разные сущности, они могут иметь, например, другая жизнь. Сессии могут быть сброшены, их TTL может быть короче / длиннее, чем TTL токена. Например, TTL сеанса django по умолчанию составляет 2 недели. Хотите усложнить логику удаленного сервера, чтобы получать новые токены каждые 2 недели? Или представьте ситуацию, когда токен скомпрометирован. Вы также хотите заставить ajax-клиента выйти из системы?

...