1

Я использую TokenAuthentication в Django REST Framework, чтобы иметь сценарий удаленного доступа к моему API. Домен, на котором запущен API, находится за сертификатом TLS.Django REST Framework с проблемой TokenAuthentication с CSRF/CORS

Я просмотрел много источников и попробовал много вариантов, прежде чем приходить сюда, чтобы выяснить, в чем моя проблема. Короче говоря, я продолжаю получать ошибку CSRF verification failed. Request aborted. при попытке опубликовать.

Вот мое мнение:

# @csrf_exempt 
@api_view(['POST']) 
@authentication_classes((TokenAuthentication,)) 
@permission_classes((permissions.IsAuthenticated,)) 
def create_object(request): 

csrf_exempt декоратор ничего не сделал здесь. Таким образом, я также попробовал его на моем urls.py:

url(r'^create_object/', csrf_exempt(views.create_object),), 

Я даже пытался писать пользовательский декоратор, и используя this suggestion. Даже когда я это делаю, я даже не могу заставить этого декоратора выполнить, прежде чем получить отказ. Возможно, есть проблема с заказом моего промежуточного ПО?

'sslify.middleware.SSLifyMiddleware', 
'django.middleware.security.SecurityMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 

'corsheaders.middleware.CorsMiddleware', 

'django.middleware.common.CommonMiddleware', 
'django.middleware.csrf.CsrfViewMiddleware', 

'corsheaders.middleware.CorsPostCsrfMiddleware', 

'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.auth.middleware.RemoteUserMiddleware', 
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware', 
'django.middleware.clickjacking.XFrameOptionsMiddleware', 

Вот мои настройки Джанго CORS:

CORS_ORIGIN_ALLOW_ALL = False 
CORS_ORIGIN_WHITELIST = ('example.com',) 
CORS_REPLACE_HTTPS_REFERER = True 
+0

Мое решение (так как я не мог понять причину) заключался в добавлении промежуточного программного обеспечения, которое выполняется перед csrf, который устанавливает флаг на объекте '' запрос'', чтобы пропустить защиту после проверки на путь запроса. Завтра я отправлю код как ответ, когда у меня появится шанс. –

ответ

1

Как и было обещано, вот решение, с которым я столкнулся. По общему признанию, это не идеально. Я не смог понять основную проблему (почему на HTTPS приложение не отвечало на csrf_exempt, или CORS_REPLACE_HTTPS_REFERER), но придумал это ограниченное решение.

ШАГ 1

Во-первых, я подклассы весь CsrfViewMiddleware класс в мою собственную версию, и поместил его в мой промежуточного слоя (изменения от оригинального quertion маркированные):

'sslify.middleware.SSLifyMiddleware', 
'django.middleware.security.SecurityMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 

'corsheaders.middleware.CorsMiddleware', 

'django.middleware.common.CommonMiddleware', 
#'django.middleware.csrf.CsrfViewMiddleware', ##CHANGE 
'myapp.csrf.CsrfViewMiddleware', ##CHANGE 

'corsheaders.middleware.CorsPostCsrfMiddleware', 

'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.auth.middleware.RemoteUserMiddleware', 
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware', 
'django.middleware.clickjacking.XFrameOptionsMiddleware', 

Около линии 160 от моя версия от CsrfViewMiddleware, я заменил существующие условные:

  acceptable_referers = ['https://%s' % u for u in settings.CORS_ORIGIN_WHITELIST] + ['http://%s' % u for u in settings.CORS_ORIGIN_WHITELIST] 
      if not same_origin(referer, good_referer) and referer not in acceptable_referers: 

Это заставило меня пройти мимо недопустимой проблемы с реферированием, что прекрасно, потому что я переименовываю области, которые в порядке. По сути, он приходит к тому же результату, что и CORS_REPLACE_HTTPS_REFERER. Моя версия перекрестно ссылается на заголовок референта с settings.CORS_ORIGIN_WHITELIST, тогда как метод CORS_REPLACE_HTTPS_REFERER временно изменяет референт request. Мне также не хватает достаточного решения для обеспечения безопасности, но это еще один разговор.

ШАГ 2

На данный момент, я все еще получаю CSRF печенье не найдена ошибка.Чтобы обойти эту проблему, и с тех пор csrf_exempt не respoding (казалось, что промежуточное программное обеспечение было выполнение слишком рано), я добавил новую часть промежуточного слоя:

'sslify.middleware.SSLifyMiddleware', 
'django.middleware.security.SecurityMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 

'myapp.csrf.CsrfSkipMiddleware' ##ADDED 

'corsheaders.middleware.CorsMiddleware', 

'django.middleware.common.CommonMiddleware', 
#'django.middleware.csrf.CsrfViewMiddleware', ##REMOVED 
'myapp.csrf.CsrfViewMiddleware', ##ADDED 

'corsheaders.middleware.CorsPostCsrfMiddleware', 

'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.auth.middleware.RemoteUserMiddleware', 
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware', 
'django.middleware.clickjacking.XFrameOptionsMiddleware', 

Эта новая часть промежуточного программного обеспечения по существу устанавливает флаг на объект запроса (_dont_enforce_csrf_checks), который уже существует в версии запаса CsrfViewMiddleware и сообщает сценарию игнорировать остальную часть проверки csrf. Чтобы это сделать, он проверяет путь страницы к списку путей, которые я выбрал для удаления из csrf, в settings.CSRF_SKIP_URLS.

class CsrfSkipMiddleware(object): 

    def process_request(self, request): 
     CSRF_SKIP_URLS = [re.compile(expr) for expr in settings.CSRF_SKIP_URLS] 
     path = request.path_info.lstrip('/') 

     if any(m.match(path) for m in CSRF_SKIP_URLS): 
      setattr(request, '_dont_enforce_csrf_checks', True) 

МЫСЛИ

Опять же, не лучшая реализация. Но для моих целей это работает. Мысли по-прежнему приветствуются.

0

я вижу, что вы используете Джанго Корс заголовки. Я столкнулся с аналогичной проблемой и указал: CORS_REPLACE_HTTPS_REFERER = True в settings.py решил проблему.

+0

Хорошая точка. Вот почему я сохранил материал CORS там. Я отредактировал свой вопрос, чтобы включить мои настройки CORS. У меня есть '' CORS_REPLACE_HTTPS_REFERER = True'' –

Смежные вопросы