Sam & Max » cookie http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 La protection CSRF de Django et les requêtes Ajax 19 http://sametmax.com/la-protection-csrf-de-django-et-les-requetes-ajax/ http://sametmax.com/la-protection-csrf-de-django-et-les-requetes-ajax/#comments Tue, 10 Jun 2014 04:18:36 +0000 http://sametmax.com/?p=10438 attaques CSRF est dans le top 10 des erreurs les plus chiantes en Django, main dans la main avec les fichiers statiques qui ne marchent pas, les URL qui ne matchent pas et les CBV qui nheuuuu, juste pas.]]> La protection contre les attaques CSRF est dans le top 10 des erreurs les plus chiantes en Django, main dans la main avec les fichiers statiques qui ne marchent pas, les URL qui ne matchent pas et les CBV qui nheuuuu, juste pas.

Une fois qu’on a compris le principe, ça va pour la prog normal, mais un jour on a besoin de faire un POST en Ajax, et on se retrouve avec une erreur invisible. Après avoir dégainé Firebug, on comprend qu’on a une 403 forbidden, et votre cerveau finit (la durée galérienne est plus ou moins longue selon les profiles, les heures de sommeil et les phases de la lune) par réaliser qu’on n’a pas envoyé le token CSRF. Merde.

C’est là que généralement les gens sortent du @csrf_exempt, ou carrément, en finissent avec cette solution radicale :

MIDDLEWARE_CLASSES = (
    'django.middleware.gzip.GZipMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

Mais c’est quand même dommage d’en arriver là alors qu’on peut le faire proprement.

D’abord, le token est sauvegardé dans un cookie. Il faut donc le récupérer.

// ue petite fonction pour récupérer la valeur d'un cookie,
// puisque bien entendu, comme toutes les APIS javascripts,
// les choses qu'on fait le plus souvent ne sont pas incluses
// en natif. Oui je suis aigri.
function getCookie(name) {
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                return decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
}

Sinon, pour les fainéants, il y a y a un plugin jquery qui permet de faire $.cookie('nom').

Ensuite, on attache cette valeur en header avec toutes les requêtes POST. Comme ça, plus besoin de l’inclure manuellement, on peut faire ses requêtes sans y penser.

Avec jQuery :

$.ajaxSetup({
    // fonction appelée avant d'envoyer une requête AJAX
    beforeSend: function(xhr, settings) {
         // on ajoute le header que si la requête est pour le site en cours
         // (URL relative) et est de type POST
         if (!/^https?:.*/.test(settings.url)  && settings.type == "POST") {
             // attachement du token dans le header
             xhr.setRequestHeader("X-CSRFToken",  getCookie('csrftoken'));
         }
     }
});

Avec AngularJs :

// interception de la configuration du provider HTTP
// qui possède un mécanisme déjà tout prêt pour ça
votre_app.config(function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
});

Attention, si l’app n’est pas servie par Django (template statique avec uniquement des appels Ajax), il faut faire au moins un GET avant de faire son premier POST afin d’obtenir le cookie.

]]>
http://sametmax.com/la-protection-csrf-de-django-et-les-requetes-ajax/feed/ 19
Simuler un cookie avec Mechanize en python http://sametmax.com/simuler-un-cookie-avec-mechanize-en-python/ http://sametmax.com/simuler-un-cookie-avec-mechanize-en-python/#comments Sun, 20 May 2012 19:46:51 +0000 http://sametmax.com/?p=667 Il peut arriver que l’on ai besoin de simuler la présence d’un cookie lors de l’exploration d’un site avec Mechanize .
Un exemple tout bête l’autre jour j’essayais de me connecter à un site qui demandait une vérif d’âge, impossible de simuler le click sur “ENTER” car le bouton était géré par Jquery (et Mechanize ne fait pas de js).
Après quelques debug je me suis aperçu que le site stockait dans un cookie la confirmation d’âge sous la forme “age_verified”, valeur 1.

il suffisait donc d’avoir ce cookie et le site nous laissait tranquille.
Avec Mechanize il est possible d’ajouter un cookie dans son cookie jar, voici comment:

import mechanize
 
# Browser use mechanize
br = mechanize.Browser()
 
# Cookie Jar
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
 
# add a cookie to cookie jar
cj.set_cookie(cookielib.Cookie(0, 'age_verified', '1', '80', False, 'www.nom_de_domaine.com', True, False, '/', True, False, None, False, None, None, None))
 
# Browser options
br.set_handle_redirect(True)

Où:
age_verified : SID du cookie
1: valeur
80: port
www.nom_de_domaine.com : le nom de domaine du site auquel le cookie appartient
/: path du cookie

Un peu plus sur les options:

cookielib.Cookie(version=0, name='SID', value=self._sid, port=None, port_specified=False, domain='.google.com', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=False, expires='1600000000', discard=False, comment=None, comment_url=None, rest={})

Quelques liens:
http://nullege.com/codes/search/cookielib.Cookie
http://docs.python.org/library/cookielib.html
http://wwwsearch.sourceforge.net/mechanize/hints.html

]]> http://sametmax.com/simuler-un-cookie-avec-mechanize-en-python/feed/ 0