Facebook iframe-приложения и Django CSRF

3 сентября 2011

Первое, что видят начинающие разработчики iframe-приложений для Facebook при обращении к их canvas view, — сообщение об ошибке CSRF. Связано это с тем, что при запуске iframe-приложения Facebook автоматически выполняет на canvas URL POST-запрос с информацией о текущем пользователе. Странно было бы ожидать в нем правильного CSRF-token. Обычной практикой является полный отказ от CSRF для Facebook. Другой вариант — это написание своих CSRF-токенов и их ручная проверка. Но небольшое исследование показало, что вполне можно пользоваться стандартным механизмом Django, если научиться проверять CSRF не всегда, а только когда это необходимо. А точнее, проверять CSRF стоит лишь в том случае, когда в POST-запросе нет корректного signed_request с access_token — его наличие недвусмысленно говорит нам о том, что POST-запрос пришел от Facebook. Вот как это решилось в нашем случае:

# Description for enlgish-speaking users:
# Easy and standard way to manage CSRF when developing Django applications for Facebook
from django.views.decorators.csrf import csrf_view_exempt
from django.middleware.csrf import CsrfViewMiddleware

# Function to check CSRF on demand (use {% csrf_token %} in your forms as usual)
def facebook_csrf_check(request):
    return CsrfViewMiddleware().process_view(request, facebook_csrf_check, None, None) == None

Функция facebook_csrf_check, собственно, является ручной проверкой на правильность CSRF. Вы можете вызывать ее при необходимости. Автоматическая проверка отключается декоратором csrf_view_exempt. Например:

# Your canvas view
@csrf_view_exempt
def facebook_canvas(request):

    if is_valid_access_token(request): # check whether a correct access_token presents
        ...

    print 'CSRF ' + str(facebook_csrf_check(request)) # facebook_csrf_check == True means CSRF is OK

facebook_csrf_check == True означает, что с csrf все в порядке.

Code snippet.