Debian, Dojo, Django, Python

Делюсь опытом в описанных технологиях. Блог в первую очередь выполняет роль памяток для меня самого.

Показаны сообщения с ярлыком csrf. Показать все сообщения
Показаны сообщения с ярлыком csrf. Показать все сообщения

CSRF-Token в Dojo Toolkit 1.x и Django

Постоянно забываю, как в Dojo Toolkit 1.x автоматически цеплять CSRF-Token к XHR-запросам. Ниже просто код, который должен запускаться при старте приложения (FrontEnd).

Где-то в загрузчике приложения...
require([
  "dojo/cookie",
  "dojo/request/notify",
  "dojo/domReady!"
], function(cookie, notify) { 
  notify("send", function(response, cancel) {
    response.xhr.setRequestHeader("X-SCRFToken", cookie("csrftoken"));
  });
});

И каждый раз забываю, как правильно выставить CSRF-Token в Django. Для этого нужно не так уж и много:

Код ниже актуален для Django 1.4. В новых версиях, например, 1.8 функция csrf перенесена в модуль django.template.context_processors
Модуль, отвечающий за прорисовку индексной страницы.
# -*- coding: utf-8 -*-

u"""Набор видов для построения базового интерфейса приложения."""

from django.shortcuts import render_to_response
from django.views.generic import View
from django.core.context_processors import csrf


class Index(View):

    u"""Главное окно приложения."""

    template_name = "index.html"

    def get(self, request):
        # Установка CSRF-токена
        c = {}
        c.update(csrf(request))
        return render_to_response(self.template_name, c)

Но этого мало. Нужно ещё в теле главной страницы разместить скрытое поле, куда будет записан токен. Кстати, только так в старых версиях Django можно указать cookie для его хранения.

index.html
<!doctype html>
<html lang="ru">
  <head>
    <meta charset="UTF-8"/>
    <title>Установка CSRF-Token'а</title>
  </head>
  <body>
    <!-- ТО САМОЕ СКРЫТОЕ ПОЛЕ -->
    <input name="csrftoken" type="hidden" value="{% csrf_token %}" />
    <!-- /ТО САМОЕ СКРЫТОЕ ПОЛЕ -->
  </body>
</html>

CSRF-токены и CBV, требующие авторизации

Всё, что нужно знать о CSRF-токенах в Django

Всё Middleware оставлены по-умолчанию, т.е. в settings.py никаких изменений не вносилось.

Ниже идёт код, который позволяет прописать в шаблон Cookies с CSRF-токеном:

from django.core.context_processors import csrf
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic import View


class Index(View):

    def get(self, request):
        context = {}
        context.update(csrf(request))
        return render_to_response(
            'index.html',
            RequestContext(request, context)
        )

В сам шаблон нужно не забыть включить одну важную строку:

{% csrf_token %}

Без этой строки печенька покрошена на страницу НЕ БУДЕТ. Не знаю, почему, просто вот такой интересный факт.

Миксин для CBV (Class Based Views), которым нужна авторизация:

from os import path

from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.views.generic import View


class LoginRequiredMixin(object):
    """Собственно примесь """

    @classmethod
    def as_view(cls, **initkwargs):
        view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
        return login_required(view, login_url='/login/')


class ProfileView(LoginRequiredMixin, View):

    def get(self, request, *args, **kwargs):
        c = {}
        c.update(csrf(request))

        user = request.user

        template_path = path.join(
            'admin',
            'index.html',
        )

        return render_to_response(
            template_path,
            RequestContext(request, c)
        )

CSRFToken в Angular 1.4

В новом Angular 1.4 одно из приятных изменений - возможность задавать куку и заголовок для CSRF-токена. Раньше делали так:

angular.module('app', ['ngCookies']).run(['$http', '$cookies', function($http, $cookies){
    var token = $cookies.csrftoken;
    $http.defaults.headers.common['X-CSRFToken'] = token;
    $http.defaults.headers.post['X-CSRFToken'] = token;
}]);

Сейчас на этапе конфигурирования приложения можно сделать такой финт:

angular.module('app', []).config(['$httpProvider', function($httpProvider){
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);

Оригинальная документация - здесь. Проверял работу на Django 1.8.