<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wiki-br.binets.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Guillaume.vizier</id>
	<title>WikiBR - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-br.binets.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Guillaume.vizier"/>
	<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/Sp%C3%A9cial:Contributions/Guillaume.vizier"/>
	<updated>2026-10-06T03:59:08Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki-br.binets.fr/index.php?title=Tuto_pour_le_d%C3%A9ploiement_des_sites_Django&amp;diff=8616</id>
		<title>Tuto pour le déploiement des sites Django</title>
		<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/index.php?title=Tuto_pour_le_d%C3%A9ploiement_des_sites_Django&amp;diff=8616"/>
		<updated>2017-03-10T22:09:24Z</updated>

		<summary type="html">&lt;p&gt;Guillaume.vizier : /* Mise en place de l&amp;#039;authentification par CAS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Connexion ==&lt;br /&gt;
&lt;br /&gt;
Assurez vous tout d&#039;abord d&#039;être administrateur de votre binet. Il faut attendre au moins une heure pour que les modifications soient prises en compte.&lt;br /&gt;
&lt;br /&gt;
Ensuite vous ouvrez votre terminal et vous vous connectez sur le serveur avec la commande ssh.&lt;br /&gt;
 ssh prenom.nom@129.104.201.52&lt;br /&gt;
&lt;br /&gt;
Une fois que vous avez tapé votre mot de passe frankiz, vous arrivez sur le serveur dans un dossier à votre nom. Il y a un fichier {{c|README.txt}} qui devrait donner un certain nombre d&#039;informations sur le fonctionnement de kevarzh ou encore sur certaines modifs à faire sur le code de votre site. Vous pouvez vous diriger sur le serveur par les commandes habituelles. Votre dossier personnel se trouve dans {{c|/hosting/user/prenom.nom}}. &lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez lancer une commande ayant besoin d&#039;internet (par exemple des commandes git) n&#039;oubliez pas de mettre {{c|proxychains}} devant votre commande.&lt;br /&gt;
&lt;br /&gt;
== Copie des fichiers ==&lt;br /&gt;
&lt;br /&gt;
Le dossier {{c|/hosting/www/nom_binet}} contient (au moins) un dossier par site. Si vous n&#039;avez qu&#039;un site, le dossier par défaut est {{c|htdocs}}. C&#039;est dans un de ces dossiers que vous allez devoir copier le code de votre site.&lt;br /&gt;
 scp -r /code_site prenom.nom@129.104.201.52:/hosting/wwww/nom_binet/version_site&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
&lt;br /&gt;
Attention ! L&#039;espace réservé à chaque binet est limité. Il faut se méfier quand on fait une copie, notamment a l&#039;environnement virtuel. D&#039;abord il pèse lourd, en plus il faudra que vous le remplaciez de toute façon. Autant ne pas le copier dès le départ...&lt;br /&gt;
Pour savoir si vous avez dépassé votre quota :&lt;br /&gt;
 quota -sg&lt;br /&gt;
Cette commande affiche, pour chaque binet, l&#039;espace utilisé, une «soft limit» et la vraie («hard») limit.&lt;br /&gt;
&lt;br /&gt;
== Virtual environment ==&lt;br /&gt;
&lt;br /&gt;
Une fois que le code du site est en place, il faut recréer l&#039;environnement virtuel.&lt;br /&gt;
 virtualenv -p /usr/bin/python3 venv&lt;br /&gt;
Il est important que vous nommiez le dossier {{c|venv}}.&lt;br /&gt;
&lt;br /&gt;
À partir de là, &#039;&#039;&#039;toutes&#039;&#039;&#039; les commandes utilisant python doivent être exécutées dans le virtualenv. Pour rentrer dans le virtualenv, vous devez lancer :&lt;br /&gt;
 source venv/bin/activate&lt;br /&gt;
&lt;br /&gt;
Une fois dans le venv, vous pouvez installer les dépendances nécessaires :&lt;br /&gt;
 proxychains pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
== Adaptations ==&lt;br /&gt;
Certaines adaptations sont nécessaires pour faire fonctionner le site. La documentation officielle de Django fournit une bonne [https://docs.djangoproject.com/fr/1.10/howto/deployment/checklist/ checklist]. Là, pas besoin de se casser la tête il suffit de suivre la liste, des liens sont là pour expliquer en détails ce que l&#039;on fait à chaque fois. Les points essentiels à ne surtout pas sauter sont :&lt;br /&gt;
* Mettre {{c|DEBUG}} à {{False}}&lt;br /&gt;
* {{c|SECRET_KEY}}:&lt;br /&gt;
Si vous utilisez un repo git, il ne faut pas mettre cette clef dans le code.&lt;br /&gt;
Un snippet possible est le suivant:&lt;br /&gt;
 keyfile = os.path.join(BASE_DIR, &amp;quot;secret.key&amp;quot;)&lt;br /&gt;
 if not os.path.exists(keyfile):&lt;br /&gt;
     with open(keyfile, &amp;quot;wb&amp;quot;) as f:&lt;br /&gt;
         f.write(base64.b64_encode(os.urandom(30)))&lt;br /&gt;
 with open(keyfile, &amp;quot;r&amp;quot;) as f:&lt;br /&gt;
     SECRET_KEY = f.read().strip()&lt;br /&gt;
&lt;br /&gt;
La clef est contenue dans le fichier {{c|secret.key}} (généré automatiquement s&#039;il n&#039;existe pas) qu&#039;il suffit de mettre dans le {{c|.gitignore}}.&lt;br /&gt;
&lt;br /&gt;
* Mettre {{c|ALLOWED_HOST}} à {{c|[&amp;quot;*&amp;quot;]}}, le filtrage a lieu avant Django&lt;br /&gt;
* STATIC_ROOT, STATIC_URL, MEDIA_ROOT et MEDIA_URL:&lt;br /&gt;
 STATIC_URL = &#039;/assets/static/&#039;&lt;br /&gt;
 STATIC_ROOT = os.path.join(BASE_DIR, &amp;quot;assets/static/&amp;quot;)&lt;br /&gt;
 MEDIA_ROOT = os.path.join(BASE_DIR, &amp;quot;assets/media/&amp;quot;)&lt;br /&gt;
 MEDIA_URL = &#039;/assets/media/&#039;&lt;br /&gt;
&lt;br /&gt;
* emails (indispensable pour être averti des erreurs 500)&lt;br /&gt;
 DEFAULT_FROM_EMAIL = &amp;quot;nom_du_binet@binets.polytechnique.fr&amp;quot;&lt;br /&gt;
 # voir https://portail.polytechnique.edu/dsi/eleves/mail-binets&lt;br /&gt;
 SERVER_EMAIL = DEFAULT_FROM_EMAIL&lt;br /&gt;
 ADMINS = [(&amp;quot;Webmaster&amp;quot;, DEFAULT_FROM_EMAIL)]&lt;br /&gt;
&lt;br /&gt;
* base de donnée : n&#039;utilisez pas sqlite ! Nous avons eu des problèmes par le passé, et les bases de données sql sont sauvegardées toutes les semaines.&lt;br /&gt;
Un snippet utilisable est :&lt;br /&gt;
 if DEBUG:&lt;br /&gt;
   DATABASES = {&lt;br /&gt;
     &#039;default&#039;: {&lt;br /&gt;
       &#039;ENGINE&#039;: &#039;django.db.backends.sqlite3&#039;,&lt;br /&gt;
       &#039;NAME&#039;: os.path.join(BASE_DIR, &#039;db.sqlite3&#039;),&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 else:&lt;br /&gt;
   DATABASES = {&lt;br /&gt;
     &#039;default&#039;: {&lt;br /&gt;
        &#039;ENGINE&#039;: &#039;django.db.backends.mysql&#039;,&lt;br /&gt;
        &#039;OPTIONS&#039;: {&lt;br /&gt;
            &#039;read_default_file&#039;: os.path.join(BASE_DIR, &#039;my.cnf&#039;),&lt;br /&gt;
        },&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Placer les mots de passe dans le fichier {{c|my.cnf}}:&lt;br /&gt;
 [client]&lt;br /&gt;
 database = NAME&lt;br /&gt;
 user = USER&lt;br /&gt;
 password = PASSWORD&lt;br /&gt;
 default-character-set = utf8&lt;br /&gt;
&lt;br /&gt;
Bien sûr il faut ajouter ce fichier dans le gitignore.&lt;br /&gt;
&lt;br /&gt;
== Mise en place de l&#039;authentification par CAS ==&lt;br /&gt;
&lt;br /&gt;
* Demander sur [https://panix.binets.fr Panix] à utiliser cette authentification. Préciser les éventuels attributs supplémentaires nécessaires (promo, section, ...).&lt;br /&gt;
* Installer le paquet django_ng_cas :&lt;br /&gt;
  pip install django-ng-cas&lt;br /&gt;
* Ajouter ce paquet à la liste des applications :&lt;br /&gt;
  INSTALLED_APPS = [&lt;br /&gt;
    ...&lt;br /&gt;
    &#039;django_ng_cas&#039;,&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Configurer la connection au serveur CAS du BR : &lt;br /&gt;
  AUTHENTICATION_BACKENDS = (&lt;br /&gt;
    &#039;django.contrib.auth.backends.ModelBackend&#039;,&lt;br /&gt;
    &#039;django_cas_ng.backends.CASBackend&#039;,&lt;br /&gt;
  )&lt;br /&gt;
  CAS_SERVER_URL = &amp;quot;https://cas.binets.fr/&amp;quot;&lt;br /&gt;
* Renseigner les pages de connexion (dans {{c|my_project/urls.py}} par exemple): &lt;br /&gt;
  from django_cas_ng.views import login, logout&lt;br /&gt;
  &lt;br /&gt;
  urlpatterns = [&lt;br /&gt;
    ...&lt;br /&gt;
    url(r&#039;^login$&#039;, login, name=&#039;cas_ng_login&#039;),&lt;br /&gt;
    url(r&#039;^logout$&#039;, logout, name=&#039;cas_ng_logout&#039;),&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Ajouter l&#039;URL d&#039;entrée : &lt;br /&gt;
  LOGIN_URL = &amp;quot;login&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Attention à forcer l&#039;authentification pour les pages concernées : &lt;br /&gt;
  from django.contrib.auth.decorators import login_required&lt;br /&gt;
  &lt;br /&gt;
  @login_required&lt;br /&gt;
  def my_awesome_view(request):&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
À noter : &lt;br /&gt;
* le nom de l&#039;utilisateur connecté se trouve dans : request.user.username (accessible dans n&#039;importe quelle vue).&lt;br /&gt;
* les attributs du [[LDAP]] peuvent être disponibles (demander les attributs nécessaires  lors de la mise en place du CAS). Ils sont alors disponibles dans request.session[&#039;attributes&#039;] .&lt;br /&gt;
* plus d&#039;option de configuration sont présentés [https://github.com/mingchen/django-cas-ng/tree/master/django_cas_ng ici]&lt;br /&gt;
&lt;br /&gt;
== À chaque modification... ==&lt;br /&gt;
* du schéma SQL:&lt;br /&gt;
 python manage.py migrate&lt;br /&gt;
* des fichiers statiques:&lt;br /&gt;
 python manage.py collectstatic&lt;br /&gt;
* du code python quel qu&#039;il soit :&lt;br /&gt;
 touch /var/run/please/restart&lt;br /&gt;
Il faut attendre 1 ou deux minutes que le système enregistre la modification, quand c&#039;est fait il affiche un message dans le terminal.&lt;br /&gt;
&lt;br /&gt;
== Tester ==&lt;br /&gt;
=== Erreurs python ===&lt;br /&gt;
La commande&lt;br /&gt;
 python manage.py runserver&lt;br /&gt;
permet de vérifier qu&#039;il n&#039;y a pas d&#039;{{c|ImportError}} ou autres. Pensez à le faire dans le virtualenv.&lt;br /&gt;
=== Erreurs web ===&lt;br /&gt;
Pour checker les changements il suffit de taper l&#039;url du site pour constater en direct les changements. Si jamais il y a un souci il y a deux emplacements pour les logs : {{c|/var/log/uwsgi/nom_binet}} ou {{c|/hosting/log/nom_binet}}.&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
* Toutes les pages affichent {{c|Internal Server Error}} pas en gras : c&#039;est une erreur de {{c|uwsgi}} qui n&#039;arrive pas à :&lt;br /&gt;
** trouver ton site&lt;br /&gt;
** trouver le virtualenv&lt;br /&gt;
** une exception est levée au démarrage du serveur ({{c|ImportError}} notamment).&lt;br /&gt;
&lt;br /&gt;
Tu peux lire les logs dans {{c|/var/log/uwsgi/&amp;lt;ton binet&amp;gt;/&amp;lt;ton site&amp;gt;.log}} et vérifier où {{c|uwsgi}} va chercher ton site dans {{c|/etc/uwsgi.d/&amp;lt;ton site&amp;gt;.json}}. S&#039;il faut modifier ce dernier fichier, demande-le au BR, tu ne peux pas le faire toi même.&lt;br /&gt;
* Toutes les pages affichent {{c|Internal Server Error(500)}} en gras : c&#039;est django. Actives les mails pour avoir des détails, mais tu as probablement oublié de lancer les migrations sur une base sql vide.&lt;/div&gt;</summary>
		<author><name>Guillaume.vizier</name></author>
	</entry>
	<entry>
		<id>https://wiki-br.binets.fr/index.php?title=Authentification_Frankiz&amp;diff=8615</id>
		<title>Authentification Frankiz</title>
		<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/index.php?title=Authentification_Frankiz&amp;diff=8615"/>
		<updated>2017-03-10T22:08:57Z</updated>

		<summary type="html">&lt;p&gt;Guillaume.vizier : /* Authentification par le CAS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Frankiz permet à des sites externes (binets en particulier) d&#039;utiliser sa base de données pour authentifier les utilisateurs.&lt;br /&gt;
&lt;br /&gt;
Le webmaster du site en question doit auparavant faire une demande de mise en place de ce système en envoyant un mail à l&#039;équipe frankiz ([mailto:web@eleves.polytechnique.fr web@eleves.polytechnique.fr]).&lt;br /&gt;
Il doit alors donner :&lt;br /&gt;
* l&#039;url complète de la page de login de son site (plus précisément, l&#039;URL de callback)&lt;br /&gt;
* les informations auxquelles il souhaite accéder&lt;br /&gt;
* une justification de la demande (et oui, on ne partage évidemment pas notre base de données avec n&#039;importe qui !)&lt;br /&gt;
&lt;br /&gt;
Si la demande est acceptée, un admin Frankiz va alors inscrire ton site dans notre base de donnée de sites externes et générer une clé qu&#039;il va te communiquer. Cette opération se déroule via l&#039;interface d&#039;administration de frankiz. Cette clé va te permettre d&#039;authentifier les échanges d&#039;informations entre frankiz et le site externe.&lt;br /&gt;
&lt;br /&gt;
==Liste des informations disponibles==&lt;br /&gt;
&lt;br /&gt;
Tu peux demander l&#039;accès aux informations &lt;br /&gt;
&lt;br /&gt;
* names : prénom, nom, surnom, identifiant Frankiz&lt;br /&gt;
* email : adresse mail&lt;br /&gt;
* photo : URL vers la photo TOL&lt;br /&gt;
* promo : nom du premier groupe promo&lt;br /&gt;
* sport : nom de la section sportive (si applicable)&lt;br /&gt;
* rights : droits dans les groupes associés&lt;br /&gt;
* binets_admin : liste des binets dont l&#039;utilisateur est administrateur&lt;br /&gt;
&lt;br /&gt;
==Code de la page d&#039;identification en PHP==&lt;br /&gt;
Ci dessous un exemple commenté de script d&#039;authentification, à mettre sur le site externe :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;fkz_auth.php&#039;;&lt;br /&gt;
if(!isset($_GET[&#039;response&#039;])){&lt;br /&gt;
  frankiz_do_auth();&lt;br /&gt;
}&lt;br /&gt;
$auth = frankiz_get_response();&lt;br /&gt;
// et voila !&lt;br /&gt;
// les données sont stockées dans $auth = array(key =&amp;gt; value, ...);&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Code des fonctions utilisées dans &#039;&#039;fkz_auth.php&#039;&#039;==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * Clé secrète fournie par l&#039;équipe frankiz lors de l&#039;inscription du site.&lt;br /&gt;
 * Cette clé sert à signer les requêtes et à authentifier le site.&lt;br /&gt;
 */&lt;br /&gt;
$FKZ_KEY = &amp;quot;000&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
function frankiz_do_auth(){&lt;br /&gt;
   global $FKZ_KEY;&lt;br /&gt;
  /**&lt;br /&gt;
   * Prendre le timestamp permet d&#039;éviter le rejet de la requête&lt;br /&gt;
   */&lt;br /&gt;
  $timestamp = time();&lt;br /&gt;
  /**&lt;br /&gt;
   * url de la page de login, doit correspondre *exactement* à celle entrée dans&lt;br /&gt;
   * la base de données de Frankiz (définie lors de l&#039;inscription)&lt;br /&gt;
   */&lt;br /&gt;
  $site = &#039;http://monsite/login&#039;;&lt;br /&gt;
  /**&lt;br /&gt;
   * Champ non utile pour l&#039;authentification et retransmis tel quel par frankiz. &lt;br /&gt;
   * Il est prévu pour pouvoir mettre en place un système de redirection après &lt;br /&gt;
   * authentification, vers la page à partir de laquelle le client avait tenté de se connecter.&lt;br /&gt;
   */&lt;br /&gt;
  $location  = &amp;quot;...&amp;quot;;&lt;br /&gt;
  /**&lt;br /&gt;
   * Nature de la requête.&lt;br /&gt;
   * Fkz renverra ici à la fois les noms de la personne mais aussi ses droits dans différents groupes.&lt;br /&gt;
   * Il faut cependant que le site ait les droits sur les informations en question (à définir lors de son inscription).&lt;br /&gt;
   */&lt;br /&gt;
  $request = json_encode(array(&#039;names&#039;, &#039;rights&#039;, &#039;email&#039;, &#039;sport&#039;, &#039;promo&#039;, &#039;photo&#039;));&lt;br /&gt;
  &lt;br /&gt;
  $hash = md5($timestamp . $site . $FKZ_KEY . $request);&lt;br /&gt;
  &lt;br /&gt;
  $remote  = &#039;https://www.frankiz.net/remote?timestamp=&#039; . $timestamp .&lt;br /&gt;
      &#039;&amp;amp;site=&#039; . $site .&lt;br /&gt;
      &#039;&amp;amp;location=&#039; . $location .&lt;br /&gt;
      &#039;&amp;amp;hash=&#039; . $hash .&lt;br /&gt;
      &#039;&amp;amp;request=&#039; . $request;&lt;br /&gt;
   header(&amp;quot;Location:&amp;quot; . $remote);&lt;br /&gt;
   exit();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function frankiz_get_response(){&lt;br /&gt;
   global $FKZ_KEY;&lt;br /&gt;
   // Read request&lt;br /&gt;
   $timestamp = (isset($_GET[&#039;timestamp&#039;]) ? $_GET[&#039;timestamp&#039;] : 0);&lt;br /&gt;
   $response  = (isset($_GET[&#039;response&#039;])  ? urldecode($_GET[&#039;response&#039;])  : &#039;&#039;);&lt;br /&gt;
   $hash      = (isset($_GET[&#039;hash&#039;])      ? $_GET[&#039;hash&#039;]      : &#039;&#039;);&lt;br /&gt;
   $location  = (isset($_GET[&#039;location&#039;])  ? $_GET[&#039;location&#039;]  : &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
   // Frankiz security protocol&lt;br /&gt;
   if (abs($timestamp - time()) &amp;gt; 600)&lt;br /&gt;
      die(&amp;quot;Délai de réponse dépassé. Annulation de la requête&amp;quot;);&lt;br /&gt;
   if (md5($timestamp . $FKZ_KEY . $response) != $hash)&lt;br /&gt;
      die(&amp;quot;Session compromise.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   $response = json_decode($response, true);&lt;br /&gt;
   $response[&#039;location&#039;] = $location;&lt;br /&gt;
&lt;br /&gt;
   // Set empty fields&lt;br /&gt;
   $fields = array(&#039;hruid&#039;,&lt;br /&gt;
     &#039;firstname&#039;, &#039;lastname&#039;, &#039;nickname&#039;,&lt;br /&gt;
     &#039;promo&#039;, &#039;photo&#039;, &#039;location&#039;);&lt;br /&gt;
   foreach ($fields as $k) {&lt;br /&gt;
      if (!isset($response[$k]))&lt;br /&gt;
      $response[$k] = &#039;&#039;;&lt;br /&gt;
   }&lt;br /&gt;
   return $response;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Avec Django==&lt;br /&gt;
=== Version sale ===&lt;br /&gt;
L&#039;interfaçage de Frankiz directement avec Django n&#039;est pas trivial, pour le faire proprement il faudrait coder un backend d&#039;authentification. En attendant, le code ci dessous est un peu sale mais marche. Il sauve l&#039;username frankiz dans la session, ce qui est raisonnablement safe normalement.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
def logout(request):&lt;br /&gt;
    del request.session[&amp;quot;username&amp;quot;]&lt;br /&gt;
    request.session.modified = True&lt;br /&gt;
    return redirect(&amp;quot;/&amp;quot;) &lt;br /&gt;
 &lt;br /&gt;
def fkz_answer(request): &lt;br /&gt;
    if not &amp;quot;timestamp&amp;quot; in request.GET.keys() or not &amp;quot;response&amp;quot; in request.GET.keys() or not &amp;quot;hash&amp;quot; in request.GET.keys(): &lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
    response = request.GET.get(&amp;quot;response&amp;quot;)&lt;br /&gt;
    ts = request.GET.get(&amp;quot;timestamp&amp;quot;)&lt;br /&gt;
    h = request.GET.get(&amp;quot;hash&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if abs(int(time.time()) - int(ts)) &amp;gt; 600:&lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if hashlib.md5(ts + FKZ_KEY + response).hexdigest() != h:&lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    data = json.loads(response)&lt;br /&gt;
    request.session[&#039;username&#039;] = data[&#039;hruid&#039;]&lt;br /&gt;
    return redirect(&amp;quot;/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def fkz_do_login(request):&lt;br /&gt;
    ts = time.time()&lt;br /&gt;
    page = &amp;quot;http://***/fkz_answer/&amp;quot;&lt;br /&gt;
    r = json.dumps([&amp;quot;names&amp;quot;, &amp;quot;email&amp;quot;])&lt;br /&gt;
    h = hashlib.md5(ts + page + FKZ_KEY + r).hexdigest()&lt;br /&gt;
    return redirect(&amp;quot;https://www.frankiz.net/remote?&amp;quot;+urlencode([(&#039;timestamp&#039;,ts),(&#039;site&#039;,page),(&#039;hash&#039;,h),(&#039;request&#039;,r)]))&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il existe cependant une autre méthode utilisant les mêmes identifiants&lt;br /&gt;
&lt;br /&gt;
=== Authentification par le CAS ===&lt;br /&gt;
&lt;br /&gt;
* Demander sur [https://panix.binets.fr Panix] à utiliser cette authentification. Préciser les éventuels attributs supplémentaires nécessaires (promo, section, ...).&lt;br /&gt;
* Installer le paquet django_ng_cas :&lt;br /&gt;
  pip install django-ng-cas&lt;br /&gt;
* Ajouter ce paquet à la liste des applications :&lt;br /&gt;
  INSTALLED_APPS = [&lt;br /&gt;
    ...&lt;br /&gt;
    &#039;django_ng_cas&#039;,&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Configurer la connection au serveur CAS du BR : &lt;br /&gt;
  AUTHENTICATION_BACKENDS = (&lt;br /&gt;
    &#039;django.contrib.auth.backends.ModelBackend&#039;,&lt;br /&gt;
    &#039;django_cas_ng.backends.CASBackend&#039;,&lt;br /&gt;
  )&lt;br /&gt;
  CAS_SERVER_URL = &amp;quot;https://cas.binets.fr/&amp;quot;&lt;br /&gt;
* Renseigner les pages de connexion (dans {{c|my_project/urls.py}} par exemple): &lt;br /&gt;
  from django_cas_ng.views import login, logout&lt;br /&gt;
  &lt;br /&gt;
  urlpatterns = [&lt;br /&gt;
    ...&lt;br /&gt;
    url(r&#039;^login$&#039;, login, name=&#039;cas_ng_login&#039;),&lt;br /&gt;
    url(r&#039;^logout$&#039;, logout, name=&#039;cas_ng_logout&#039;),&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Ajouter l&#039;URL d&#039;entrée : &lt;br /&gt;
  LOGIN_URL = &amp;quot;login&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Attention à forcer l&#039;authentification pour les pages concernées : &lt;br /&gt;
  from django.contrib.auth.decorators import login_required&lt;br /&gt;
  &lt;br /&gt;
  @login_required&lt;br /&gt;
  def my_awesome_view(request):&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
À noter : &lt;br /&gt;
* le nom de l&#039;utilisateur connecté se trouve dans : request.user.username (accessible dans n&#039;importe quelle vue).&lt;br /&gt;
* les attributs du [[LDAP]] peuvent être disponibles (demander les attributs nécessaires  lors de la mise en place du CAS). Ils sont alors disponibles dans request.session[&#039;attributes&#039;] .&lt;br /&gt;
* plus d&#039;option de configuration sont présentés [https://github.com/mingchen/django-cas-ng/tree/master/django_cas_ng ici]&lt;br /&gt;
&lt;br /&gt;
==Avec Drupal==&lt;br /&gt;
&lt;br /&gt;
L&#039;implémentation de l&#039;authentification avec un CMS comme Drupal n&#039;est pas forcément évidente. Si vous avez une question, vous pouvez contacter [mailto:antoine.sauvage@polytechnique.edu Antoine Sauvage]&lt;br /&gt;
&lt;br /&gt;
==Bugs vécus==&lt;br /&gt;
&lt;br /&gt;
Si l&#039;authentification ne fonctionne pas sur certains navigateurs, vérifier les variables $_GET car elles sont peut être doublement encodées. Dans ce cas, soit refaire &#039;&#039;&#039;urldecode&#039;&#039;&#039;, soit un &lt;br /&gt;
 $s = str_replace(&#039;%22&#039;,&#039;&amp;quot;&#039;,$s);&lt;br /&gt;
Si il y a un problème avec les encodages en \u&#039;&#039;machinchose&#039;&#039; pour les caractères accentués, voila une fonction qui peut vous servir (reconversion en UTF-8) :&lt;br /&gt;
 function jsonClean($s) {&lt;br /&gt;
   return preg_replace(&amp;quot;/\\\\u([a-f0-9]{4})/e&amp;quot;, &amp;quot;iconv(&#039;UCS-4LE&#039;,&#039;UTF-8&#039;,pack(&#039;V&#039;, hexdec(&#039;U$1&#039;)))&amp;quot;,$s);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:Dev]]&lt;/div&gt;</summary>
		<author><name>Guillaume.vizier</name></author>
	</entry>
	<entry>
		<id>https://wiki-br.binets.fr/index.php?title=Authentification_Frankiz&amp;diff=8614</id>
		<title>Authentification Frankiz</title>
		<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/index.php?title=Authentification_Frankiz&amp;diff=8614"/>
		<updated>2017-03-10T22:07:48Z</updated>

		<summary type="html">&lt;p&gt;Guillaume.vizier : /* Authentification CAS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Frankiz permet à des sites externes (binets en particulier) d&#039;utiliser sa base de données pour authentifier les utilisateurs.&lt;br /&gt;
&lt;br /&gt;
Le webmaster du site en question doit auparavant faire une demande de mise en place de ce système en envoyant un mail à l&#039;équipe frankiz ([mailto:web@eleves.polytechnique.fr web@eleves.polytechnique.fr]).&lt;br /&gt;
Il doit alors donner :&lt;br /&gt;
* l&#039;url complète de la page de login de son site (plus précisément, l&#039;URL de callback)&lt;br /&gt;
* les informations auxquelles il souhaite accéder&lt;br /&gt;
* une justification de la demande (et oui, on ne partage évidemment pas notre base de données avec n&#039;importe qui !)&lt;br /&gt;
&lt;br /&gt;
Si la demande est acceptée, un admin Frankiz va alors inscrire ton site dans notre base de donnée de sites externes et générer une clé qu&#039;il va te communiquer. Cette opération se déroule via l&#039;interface d&#039;administration de frankiz. Cette clé va te permettre d&#039;authentifier les échanges d&#039;informations entre frankiz et le site externe.&lt;br /&gt;
&lt;br /&gt;
==Liste des informations disponibles==&lt;br /&gt;
&lt;br /&gt;
Tu peux demander l&#039;accès aux informations &lt;br /&gt;
&lt;br /&gt;
* names : prénom, nom, surnom, identifiant Frankiz&lt;br /&gt;
* email : adresse mail&lt;br /&gt;
* photo : URL vers la photo TOL&lt;br /&gt;
* promo : nom du premier groupe promo&lt;br /&gt;
* sport : nom de la section sportive (si applicable)&lt;br /&gt;
* rights : droits dans les groupes associés&lt;br /&gt;
* binets_admin : liste des binets dont l&#039;utilisateur est administrateur&lt;br /&gt;
&lt;br /&gt;
==Code de la page d&#039;identification en PHP==&lt;br /&gt;
Ci dessous un exemple commenté de script d&#039;authentification, à mettre sur le site externe :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;fkz_auth.php&#039;;&lt;br /&gt;
if(!isset($_GET[&#039;response&#039;])){&lt;br /&gt;
  frankiz_do_auth();&lt;br /&gt;
}&lt;br /&gt;
$auth = frankiz_get_response();&lt;br /&gt;
// et voila !&lt;br /&gt;
// les données sont stockées dans $auth = array(key =&amp;gt; value, ...);&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Code des fonctions utilisées dans &#039;&#039;fkz_auth.php&#039;&#039;==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * Clé secrète fournie par l&#039;équipe frankiz lors de l&#039;inscription du site.&lt;br /&gt;
 * Cette clé sert à signer les requêtes et à authentifier le site.&lt;br /&gt;
 */&lt;br /&gt;
$FKZ_KEY = &amp;quot;000&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
function frankiz_do_auth(){&lt;br /&gt;
   global $FKZ_KEY;&lt;br /&gt;
  /**&lt;br /&gt;
   * Prendre le timestamp permet d&#039;éviter le rejet de la requête&lt;br /&gt;
   */&lt;br /&gt;
  $timestamp = time();&lt;br /&gt;
  /**&lt;br /&gt;
   * url de la page de login, doit correspondre *exactement* à celle entrée dans&lt;br /&gt;
   * la base de données de Frankiz (définie lors de l&#039;inscription)&lt;br /&gt;
   */&lt;br /&gt;
  $site = &#039;http://monsite/login&#039;;&lt;br /&gt;
  /**&lt;br /&gt;
   * Champ non utile pour l&#039;authentification et retransmis tel quel par frankiz. &lt;br /&gt;
   * Il est prévu pour pouvoir mettre en place un système de redirection après &lt;br /&gt;
   * authentification, vers la page à partir de laquelle le client avait tenté de se connecter.&lt;br /&gt;
   */&lt;br /&gt;
  $location  = &amp;quot;...&amp;quot;;&lt;br /&gt;
  /**&lt;br /&gt;
   * Nature de la requête.&lt;br /&gt;
   * Fkz renverra ici à la fois les noms de la personne mais aussi ses droits dans différents groupes.&lt;br /&gt;
   * Il faut cependant que le site ait les droits sur les informations en question (à définir lors de son inscription).&lt;br /&gt;
   */&lt;br /&gt;
  $request = json_encode(array(&#039;names&#039;, &#039;rights&#039;, &#039;email&#039;, &#039;sport&#039;, &#039;promo&#039;, &#039;photo&#039;));&lt;br /&gt;
  &lt;br /&gt;
  $hash = md5($timestamp . $site . $FKZ_KEY . $request);&lt;br /&gt;
  &lt;br /&gt;
  $remote  = &#039;https://www.frankiz.net/remote?timestamp=&#039; . $timestamp .&lt;br /&gt;
      &#039;&amp;amp;site=&#039; . $site .&lt;br /&gt;
      &#039;&amp;amp;location=&#039; . $location .&lt;br /&gt;
      &#039;&amp;amp;hash=&#039; . $hash .&lt;br /&gt;
      &#039;&amp;amp;request=&#039; . $request;&lt;br /&gt;
   header(&amp;quot;Location:&amp;quot; . $remote);&lt;br /&gt;
   exit();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function frankiz_get_response(){&lt;br /&gt;
   global $FKZ_KEY;&lt;br /&gt;
   // Read request&lt;br /&gt;
   $timestamp = (isset($_GET[&#039;timestamp&#039;]) ? $_GET[&#039;timestamp&#039;] : 0);&lt;br /&gt;
   $response  = (isset($_GET[&#039;response&#039;])  ? urldecode($_GET[&#039;response&#039;])  : &#039;&#039;);&lt;br /&gt;
   $hash      = (isset($_GET[&#039;hash&#039;])      ? $_GET[&#039;hash&#039;]      : &#039;&#039;);&lt;br /&gt;
   $location  = (isset($_GET[&#039;location&#039;])  ? $_GET[&#039;location&#039;]  : &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
   // Frankiz security protocol&lt;br /&gt;
   if (abs($timestamp - time()) &amp;gt; 600)&lt;br /&gt;
      die(&amp;quot;Délai de réponse dépassé. Annulation de la requête&amp;quot;);&lt;br /&gt;
   if (md5($timestamp . $FKZ_KEY . $response) != $hash)&lt;br /&gt;
      die(&amp;quot;Session compromise.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   $response = json_decode($response, true);&lt;br /&gt;
   $response[&#039;location&#039;] = $location;&lt;br /&gt;
&lt;br /&gt;
   // Set empty fields&lt;br /&gt;
   $fields = array(&#039;hruid&#039;,&lt;br /&gt;
     &#039;firstname&#039;, &#039;lastname&#039;, &#039;nickname&#039;,&lt;br /&gt;
     &#039;promo&#039;, &#039;photo&#039;, &#039;location&#039;);&lt;br /&gt;
   foreach ($fields as $k) {&lt;br /&gt;
      if (!isset($response[$k]))&lt;br /&gt;
      $response[$k] = &#039;&#039;;&lt;br /&gt;
   }&lt;br /&gt;
   return $response;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Avec Django==&lt;br /&gt;
=== Version sale ===&lt;br /&gt;
L&#039;interfaçage de Frankiz directement avec Django n&#039;est pas trivial, pour le faire proprement il faudrait coder un backend d&#039;authentification. En attendant, le code ci dessous est un peu sale mais marche. Il sauve l&#039;username frankiz dans la session, ce qui est raisonnablement safe normalement.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
def logout(request):&lt;br /&gt;
    del request.session[&amp;quot;username&amp;quot;]&lt;br /&gt;
    request.session.modified = True&lt;br /&gt;
    return redirect(&amp;quot;/&amp;quot;) &lt;br /&gt;
 &lt;br /&gt;
def fkz_answer(request): &lt;br /&gt;
    if not &amp;quot;timestamp&amp;quot; in request.GET.keys() or not &amp;quot;response&amp;quot; in request.GET.keys() or not &amp;quot;hash&amp;quot; in request.GET.keys(): &lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
    response = request.GET.get(&amp;quot;response&amp;quot;)&lt;br /&gt;
    ts = request.GET.get(&amp;quot;timestamp&amp;quot;)&lt;br /&gt;
    h = request.GET.get(&amp;quot;hash&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if abs(int(time.time()) - int(ts)) &amp;gt; 600:&lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if hashlib.md5(ts + FKZ_KEY + response).hexdigest() != h:&lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    data = json.loads(response)&lt;br /&gt;
    request.session[&#039;username&#039;] = data[&#039;hruid&#039;]&lt;br /&gt;
    return redirect(&amp;quot;/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def fkz_do_login(request):&lt;br /&gt;
    ts = time.time()&lt;br /&gt;
    page = &amp;quot;http://***/fkz_answer/&amp;quot;&lt;br /&gt;
    r = json.dumps([&amp;quot;names&amp;quot;, &amp;quot;email&amp;quot;])&lt;br /&gt;
    h = hashlib.md5(ts + page + FKZ_KEY + r).hexdigest()&lt;br /&gt;
    return redirect(&amp;quot;https://www.frankiz.net/remote?&amp;quot;+urlencode([(&#039;timestamp&#039;,ts),(&#039;site&#039;,page),(&#039;hash&#039;,h),(&#039;request&#039;,r)]))&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il existe cependant une autre méthode utilisant les mêmes identifiants&lt;br /&gt;
&lt;br /&gt;
=== Authentification par le CAS ===&lt;br /&gt;
&lt;br /&gt;
* Demander sur [https://panix.binets.fr Panix] à utiliser cette authentification. Préciser les éventuels attributs supplémentaires nécessaires (promo, section, ...).&lt;br /&gt;
* Installer le paquet django_ng_cas :&lt;br /&gt;
  pip install django-ng-cas&lt;br /&gt;
* Ajouter ce paquet à la liste des applications :&lt;br /&gt;
  INSTALLED_APPS = [&lt;br /&gt;
    ...&lt;br /&gt;
    &#039;django_ng_cas&#039;,&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Configurer la connection au serveur CAS du BR : &lt;br /&gt;
  AUTHENTICATION_BACKENDS = (&lt;br /&gt;
    &#039;django.contrib.auth.backends.ModelBackend&#039;,&lt;br /&gt;
    &#039;django_cas_ng.backends.CASBackend&#039;,&lt;br /&gt;
  )&lt;br /&gt;
  CAS_SERVER_URL = &amp;quot;https://cas.binets.fr/&amp;quot;&lt;br /&gt;
* Renseigner les pages de connexion (dans {{c|my_project/urls.py}} par exemple): &lt;br /&gt;
  from django_cas_ng.views import login, logout&lt;br /&gt;
  &lt;br /&gt;
  urlpatterns = [&lt;br /&gt;
    ...&lt;br /&gt;
    url(r&#039;^login$&#039;, login, name=&#039;cas_ng_login&#039;),&lt;br /&gt;
    url(r&#039;^logout$&#039;, logout, name=&#039;cas_ng_logout&#039;),&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Ajouter l&#039;URL d&#039;entrée : &lt;br /&gt;
  LOGIN_URL = &amp;quot;login&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Attention à forcer l&#039;authentification pour les pages concernées : &lt;br /&gt;
  from django.contrib.auth.decorators import login_required&lt;br /&gt;
  &lt;br /&gt;
  @login_required&lt;br /&gt;
  def my_awesome_view(request):&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
À noter : &lt;br /&gt;
* le nom de l&#039;utilisateur connecté se trouve dans : request.user.username (accessible dans n&#039;importe quelle vue).&lt;br /&gt;
* les attributs du {{LDAP}} peuvent être disponibles (demander les attributs nécessaires  lors de la mise en place du CAS). Ils sont alors disponibles dans request.session[&#039;attributes&#039;] .&lt;br /&gt;
* plus d&#039;option de configuration sont présentés [https://github.com/mingchen/django-cas-ng/tree/master/django_cas_ng ici]&lt;br /&gt;
&lt;br /&gt;
==Avec Drupal==&lt;br /&gt;
&lt;br /&gt;
L&#039;implémentation de l&#039;authentification avec un CMS comme Drupal n&#039;est pas forcément évidente. Si vous avez une question, vous pouvez contacter [mailto:antoine.sauvage@polytechnique.edu Antoine Sauvage]&lt;br /&gt;
&lt;br /&gt;
==Bugs vécus==&lt;br /&gt;
&lt;br /&gt;
Si l&#039;authentification ne fonctionne pas sur certains navigateurs, vérifier les variables $_GET car elles sont peut être doublement encodées. Dans ce cas, soit refaire &#039;&#039;&#039;urldecode&#039;&#039;&#039;, soit un &lt;br /&gt;
 $s = str_replace(&#039;%22&#039;,&#039;&amp;quot;&#039;,$s);&lt;br /&gt;
Si il y a un problème avec les encodages en \u&#039;&#039;machinchose&#039;&#039; pour les caractères accentués, voila une fonction qui peut vous servir (reconversion en UTF-8) :&lt;br /&gt;
 function jsonClean($s) {&lt;br /&gt;
   return preg_replace(&amp;quot;/\\\\u([a-f0-9]{4})/e&amp;quot;, &amp;quot;iconv(&#039;UCS-4LE&#039;,&#039;UTF-8&#039;,pack(&#039;V&#039;, hexdec(&#039;U$1&#039;)))&amp;quot;,$s);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:Dev]]&lt;/div&gt;</summary>
		<author><name>Guillaume.vizier</name></author>
	</entry>
	<entry>
		<id>https://wiki-br.binets.fr/index.php?title=Tuto_pour_le_d%C3%A9ploiement_des_sites_Django&amp;diff=8613</id>
		<title>Tuto pour le déploiement des sites Django</title>
		<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/index.php?title=Tuto_pour_le_d%C3%A9ploiement_des_sites_Django&amp;diff=8613"/>
		<updated>2017-03-10T22:04:38Z</updated>

		<summary type="html">&lt;p&gt;Guillaume.vizier : /* Authentification CAS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Connexion ==&lt;br /&gt;
&lt;br /&gt;
Assurez vous tout d&#039;abord d&#039;être administrateur de votre binet. Il faut attendre au moins une heure pour que les modifications soient prises en compte.&lt;br /&gt;
&lt;br /&gt;
Ensuite vous ouvrez votre terminal et vous vous connectez sur le serveur avec la commande ssh.&lt;br /&gt;
 ssh prenom.nom@129.104.201.52&lt;br /&gt;
&lt;br /&gt;
Une fois que vous avez tapé votre mot de passe frankiz, vous arrivez sur le serveur dans un dossier à votre nom. Il y a un fichier {{c|README.txt}} qui devrait donner un certain nombre d&#039;informations sur le fonctionnement de kevarzh ou encore sur certaines modifs à faire sur le code de votre site. Vous pouvez vous diriger sur le serveur par les commandes habituelles. Votre dossier personnel se trouve dans {{c|/hosting/user/prenom.nom}}. &lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez lancer une commande ayant besoin d&#039;internet (par exemple des commandes git) n&#039;oubliez pas de mettre {{c|proxychains}} devant votre commande.&lt;br /&gt;
&lt;br /&gt;
== Copie des fichiers ==&lt;br /&gt;
&lt;br /&gt;
Le dossier {{c|/hosting/www/nom_binet}} contient (au moins) un dossier par site. Si vous n&#039;avez qu&#039;un site, le dossier par défaut est {{c|htdocs}}. C&#039;est dans un de ces dossiers que vous allez devoir copier le code de votre site.&lt;br /&gt;
 scp -r /code_site prenom.nom@129.104.201.52:/hosting/wwww/nom_binet/version_site&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
&lt;br /&gt;
Attention ! L&#039;espace réservé à chaque binet est limité. Il faut se méfier quand on fait une copie, notamment a l&#039;environnement virtuel. D&#039;abord il pèse lourd, en plus il faudra que vous le remplaciez de toute façon. Autant ne pas le copier dès le départ...&lt;br /&gt;
Pour savoir si vous avez dépassé votre quota :&lt;br /&gt;
 quota -sg&lt;br /&gt;
Cette commande affiche, pour chaque binet, l&#039;espace utilisé, une «soft limit» et la vraie («hard») limit.&lt;br /&gt;
&lt;br /&gt;
== Virtual environment ==&lt;br /&gt;
&lt;br /&gt;
Une fois que le code du site est en place, il faut recréer l&#039;environnement virtuel.&lt;br /&gt;
 virtualenv -p /usr/bin/python3 venv&lt;br /&gt;
Il est important que vous nommiez le dossier {{c|venv}}.&lt;br /&gt;
&lt;br /&gt;
À partir de là, &#039;&#039;&#039;toutes&#039;&#039;&#039; les commandes utilisant python doivent être exécutées dans le virtualenv. Pour rentrer dans le virtualenv, vous devez lancer :&lt;br /&gt;
 source venv/bin/activate&lt;br /&gt;
&lt;br /&gt;
Une fois dans le venv, vous pouvez installer les dépendances nécessaires :&lt;br /&gt;
 proxychains pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
== Adaptations ==&lt;br /&gt;
Certaines adaptations sont nécessaires pour faire fonctionner le site. La documentation officielle de Django fournit une bonne [https://docs.djangoproject.com/fr/1.10/howto/deployment/checklist/ checklist]. Là, pas besoin de se casser la tête il suffit de suivre la liste, des liens sont là pour expliquer en détails ce que l&#039;on fait à chaque fois. Les points essentiels à ne surtout pas sauter sont :&lt;br /&gt;
* Mettre {{c|DEBUG}} à {{False}}&lt;br /&gt;
* {{c|SECRET_KEY}}:&lt;br /&gt;
Si vous utilisez un repo git, il ne faut pas mettre cette clef dans le code.&lt;br /&gt;
Un snippet possible est le suivant:&lt;br /&gt;
 keyfile = os.path.join(BASE_DIR, &amp;quot;secret.key&amp;quot;)&lt;br /&gt;
 if not os.path.exists(keyfile):&lt;br /&gt;
     with open(keyfile, &amp;quot;wb&amp;quot;) as f:&lt;br /&gt;
         f.write(base64.b64_encode(os.urandom(30)))&lt;br /&gt;
 with open(keyfile, &amp;quot;r&amp;quot;) as f:&lt;br /&gt;
     SECRET_KEY = f.read().strip()&lt;br /&gt;
&lt;br /&gt;
La clef est contenue dans le fichier {{c|secret.key}} (généré automatiquement s&#039;il n&#039;existe pas) qu&#039;il suffit de mettre dans le {{c|.gitignore}}.&lt;br /&gt;
&lt;br /&gt;
* Mettre {{c|ALLOWED_HOST}} à {{c|[&amp;quot;*&amp;quot;]}}, le filtrage a lieu avant Django&lt;br /&gt;
* STATIC_ROOT, STATIC_URL, MEDIA_ROOT et MEDIA_URL:&lt;br /&gt;
 STATIC_URL = &#039;/assets/static/&#039;&lt;br /&gt;
 STATIC_ROOT = os.path.join(BASE_DIR, &amp;quot;assets/static/&amp;quot;)&lt;br /&gt;
 MEDIA_ROOT = os.path.join(BASE_DIR, &amp;quot;assets/media/&amp;quot;)&lt;br /&gt;
 MEDIA_URL = &#039;/assets/media/&#039;&lt;br /&gt;
&lt;br /&gt;
* emails (indispensable pour être averti des erreurs 500)&lt;br /&gt;
 DEFAULT_FROM_EMAIL = &amp;quot;nom_du_binet@binets.polytechnique.fr&amp;quot;&lt;br /&gt;
 # voir https://portail.polytechnique.edu/dsi/eleves/mail-binets&lt;br /&gt;
 SERVER_EMAIL = DEFAULT_FROM_EMAIL&lt;br /&gt;
 ADMINS = [(&amp;quot;Webmaster&amp;quot;, DEFAULT_FROM_EMAIL)]&lt;br /&gt;
&lt;br /&gt;
* base de donnée : n&#039;utilisez pas sqlite ! Nous avons eu des problèmes par le passé, et les bases de données sql sont sauvegardées toutes les semaines.&lt;br /&gt;
Un snippet utilisable est :&lt;br /&gt;
 if DEBUG:&lt;br /&gt;
   DATABASES = {&lt;br /&gt;
     &#039;default&#039;: {&lt;br /&gt;
       &#039;ENGINE&#039;: &#039;django.db.backends.sqlite3&#039;,&lt;br /&gt;
       &#039;NAME&#039;: os.path.join(BASE_DIR, &#039;db.sqlite3&#039;),&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 else:&lt;br /&gt;
   DATABASES = {&lt;br /&gt;
     &#039;default&#039;: {&lt;br /&gt;
        &#039;ENGINE&#039;: &#039;django.db.backends.mysql&#039;,&lt;br /&gt;
        &#039;OPTIONS&#039;: {&lt;br /&gt;
            &#039;read_default_file&#039;: os.path.join(BASE_DIR, &#039;my.cnf&#039;),&lt;br /&gt;
        },&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Placer les mots de passe dans le fichier {{c|my.cnf}}:&lt;br /&gt;
 [client]&lt;br /&gt;
 database = NAME&lt;br /&gt;
 user = USER&lt;br /&gt;
 password = PASSWORD&lt;br /&gt;
 default-character-set = utf8&lt;br /&gt;
&lt;br /&gt;
Bien sûr il faut ajouter ce fichier dans le gitignore.&lt;br /&gt;
&lt;br /&gt;
== Mise en place de l&#039;authentification par CAS ==&lt;br /&gt;
&lt;br /&gt;
* Demander sur [https://panix.binets.fr Panix] à utiliser cette authentification. Préciser les éventuels attributs supplémentaires nécessaires (promo, section, ...).&lt;br /&gt;
* Installer le paquet django_ng_cas :&lt;br /&gt;
  pip install django-ng-cas&lt;br /&gt;
* Ajouter ce paquet à la liste des applications :&lt;br /&gt;
  INSTALLED_APPS = [&lt;br /&gt;
    ...&lt;br /&gt;
    &#039;django_ng_cas&#039;,&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Configurer la connection au serveur CAS du BR : &lt;br /&gt;
  AUTHENTICATION_BACKENDS = (&lt;br /&gt;
    &#039;django.contrib.auth.backends.ModelBackend&#039;,&lt;br /&gt;
    &#039;django_cas_ng.backends.CASBackend&#039;,&lt;br /&gt;
  )&lt;br /&gt;
  CAS_SERVER_URL = &amp;quot;https://cas.binets.fr/&amp;quot;&lt;br /&gt;
* Renseigner les pages de connexion (dans {{c|my_project/urls.py}} par exemple): &lt;br /&gt;
  from django_cas_ng.views import login, logout&lt;br /&gt;
  &lt;br /&gt;
  urlpatterns = [&lt;br /&gt;
    ...&lt;br /&gt;
    url(r&#039;^login$&#039;, login, name=&#039;cas_ng_login&#039;),&lt;br /&gt;
    url(r&#039;^logout$&#039;, logout, name=&#039;cas_ng_logout&#039;),&lt;br /&gt;
    ...&lt;br /&gt;
  ]&lt;br /&gt;
* Ajouter l&#039;URL d&#039;entrée : &lt;br /&gt;
  LOGIN_URL = &amp;quot;login&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Attention à forcer l&#039;authentification pour les pages concernées : &lt;br /&gt;
  from django.contrib.auth.decorators import login_required&lt;br /&gt;
  &lt;br /&gt;
  @login_required&lt;br /&gt;
  def my_awesome_view(request):&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
À noter : &lt;br /&gt;
* le nom de l&#039;utilisateur connecté se trouve dans : request.user.username (accessible dans n&#039;importe quelle vue).&lt;br /&gt;
* les attributs du {{LDAP}} peuvent être disponibles (demander les attributs nécessaires  lors de la mise en place du CAS). Ils sont alors disponibles dans request.session[&#039;attributes&#039;] .&lt;br /&gt;
* plus d&#039;option de configuration sont présentés [https://github.com/mingchen/django-cas-ng/tree/master/django_cas_ng ici]&lt;br /&gt;
&lt;br /&gt;
== À chaque modification... ==&lt;br /&gt;
* du schéma SQL:&lt;br /&gt;
 python manage.py migrate&lt;br /&gt;
* des fichiers statiques:&lt;br /&gt;
 python manage.py collectstatic&lt;br /&gt;
* du code python quel qu&#039;il soit :&lt;br /&gt;
 touch /var/run/please/restart&lt;br /&gt;
Il faut attendre 1 ou deux minutes que le système enregistre la modification, quand c&#039;est fait il affiche un message dans le terminal.&lt;br /&gt;
&lt;br /&gt;
== Tester ==&lt;br /&gt;
=== Erreurs python ===&lt;br /&gt;
La commande&lt;br /&gt;
 python manage.py runserver&lt;br /&gt;
permet de vérifier qu&#039;il n&#039;y a pas d&#039;{{c|ImportError}} ou autres. Pensez à le faire dans le virtualenv.&lt;br /&gt;
=== Erreurs web ===&lt;br /&gt;
Pour checker les changements il suffit de taper l&#039;url du site pour constater en direct les changements. Si jamais il y a un souci il y a deux emplacements pour les logs : {{c|/var/log/uwsgi/nom_binet}} ou {{c|/hosting/log/nom_binet}}.&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
* Toutes les pages affichent {{c|Internal Server Error}} pas en gras : c&#039;est une erreur de {{c|uwsgi}} qui n&#039;arrive pas à :&lt;br /&gt;
** trouver ton site&lt;br /&gt;
** trouver le virtualenv&lt;br /&gt;
** une exception est levée au démarrage du serveur ({{c|ImportError}} notamment).&lt;br /&gt;
&lt;br /&gt;
Tu peux lire les logs dans {{c|/var/log/uwsgi/&amp;lt;ton binet&amp;gt;/&amp;lt;ton site&amp;gt;.log}} et vérifier où {{c|uwsgi}} va chercher ton site dans {{c|/etc/uwsgi.d/&amp;lt;ton site&amp;gt;.json}}. S&#039;il faut modifier ce dernier fichier, demande-le au BR, tu ne peux pas le faire toi même.&lt;br /&gt;
* Toutes les pages affichent {{c|Internal Server Error(500)}} en gras : c&#039;est django. Actives les mails pour avoir des détails, mais tu as probablement oublié de lancer les migrations sur une base sql vide.&lt;/div&gt;</summary>
		<author><name>Guillaume.vizier</name></author>
	</entry>
	<entry>
		<id>https://wiki-br.binets.fr/index.php?title=Tuto_pour_le_d%C3%A9ploiement_des_sites_Django&amp;diff=8612</id>
		<title>Tuto pour le déploiement des sites Django</title>
		<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/index.php?title=Tuto_pour_le_d%C3%A9ploiement_des_sites_Django&amp;diff=8612"/>
		<updated>2017-03-10T20:54:29Z</updated>

		<summary type="html">&lt;p&gt;Guillaume.vizier : /* À chaque modification... */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Connexion ==&lt;br /&gt;
&lt;br /&gt;
Assurez vous tout d&#039;abord d&#039;être administrateur de votre binet. Il faut attendre au moins une heure pour que les modifications soient prises en compte.&lt;br /&gt;
&lt;br /&gt;
Ensuite vous ouvrez votre terminal et vous vous connectez sur le serveur avec la commande ssh.&lt;br /&gt;
 ssh prenom.nom@129.104.201.52&lt;br /&gt;
&lt;br /&gt;
Une fois que vous avez tapé votre mot de passe frankiz, vous arrivez sur le serveur dans un dossier à votre nom. Il y a un fichier {{c|README.txt}} qui devrait donner un certain nombre d&#039;informations sur le fonctionnement de kevarzh ou encore sur certaines modifs à faire sur le code de votre site. Vous pouvez vous diriger sur le serveur par les commandes habituelles. Votre dossier personnel se trouve dans {{c|/hosting/user/prenom.nom}}. &lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez lancer une commande ayant besoin d&#039;internet (par exemple des commandes git) n&#039;oubliez pas de mettre {{c|proxychains}} devant votre commande.&lt;br /&gt;
&lt;br /&gt;
== Copie des fichiers ==&lt;br /&gt;
&lt;br /&gt;
Le dossier {{c|/hosting/www/nom_binet}} contient (au moins) un dossier par site. Si vous n&#039;avez qu&#039;un site, le dossier par défaut est {{c|htdocs}}. C&#039;est dans un de ces dossiers que vous allez devoir copier le code de votre site.&lt;br /&gt;
 scp -r /code_site prenom.nom@129.104.201.52:/hosting/wwww/nom_binet/version_site&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
&lt;br /&gt;
Attention ! L&#039;espace réservé à chaque binet est limité. Il faut se méfier quand on fait une copie, notamment a l&#039;environnement virtuel. D&#039;abord il pèse lourd, en plus il faudra que vous le remplaciez de toute façon. Autant ne pas le copier dès le départ...&lt;br /&gt;
Pour savoir si vous avez dépassé votre quota :&lt;br /&gt;
 quota -sg&lt;br /&gt;
Cette commande affiche, pour chaque binet, l&#039;espace utilisé, une «soft limit» et la vraie («hard») limit.&lt;br /&gt;
&lt;br /&gt;
== Virtual environment ==&lt;br /&gt;
&lt;br /&gt;
Une fois que le code du site est en place, il faut recréer l&#039;environnement virtuel.&lt;br /&gt;
 virtualenv -p /usr/bin/python3 venv&lt;br /&gt;
Il est important que vous nommiez le dossier {{c|venv}}.&lt;br /&gt;
&lt;br /&gt;
À partir de là, &#039;&#039;&#039;toutes&#039;&#039;&#039; les commandes utilisant python doivent être exécutées dans le virtualenv. Pour rentrer dans le virtualenv, vous devez lancer :&lt;br /&gt;
 source venv/bin/activate&lt;br /&gt;
&lt;br /&gt;
Une fois dans le venv, vous pouvez installer les dépendances nécessaires :&lt;br /&gt;
 proxychains pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
== Adaptations ==&lt;br /&gt;
Certaines adaptations sont nécessaires pour faire fonctionner le site. La documentation officielle de Django fournit une bonne [https://docs.djangoproject.com/fr/1.10/howto/deployment/checklist/ checklist]. Là, pas besoin de se casser la tête il suffit de suivre la liste, des liens sont là pour expliquer en détails ce que l&#039;on fait à chaque fois. Les points essentiels à ne surtout pas sauter sont :&lt;br /&gt;
* Mettre {{c|DEBUG}} à {{False}}&lt;br /&gt;
* {{c|SECRET_KEY}}:&lt;br /&gt;
Si vous utilisez un repo git, il ne faut pas mettre cette clef dans le code.&lt;br /&gt;
Un snippet possible est le suivant:&lt;br /&gt;
 keyfile = os.path.join(BASE_DIR, &amp;quot;secret.key&amp;quot;)&lt;br /&gt;
 if not os.path.exists(keyfile):&lt;br /&gt;
     with open(keyfile, &amp;quot;wb&amp;quot;) as f:&lt;br /&gt;
         f.write(base64.b64_encode(os.urandom(30)))&lt;br /&gt;
 with open(keyfile, &amp;quot;r&amp;quot;) as f:&lt;br /&gt;
     SECRET_KEY = f.read().strip()&lt;br /&gt;
&lt;br /&gt;
La clef est contenue dans le fichier {{c|secret.key}} (généré automatiquement s&#039;il n&#039;existe pas) qu&#039;il suffit de mettre dans le {{c|.gitignore}}.&lt;br /&gt;
&lt;br /&gt;
* Mettre {{c|ALLOWED_HOST}} à {{c|[&amp;quot;*&amp;quot;]}}, le filtrage a lieu avant Django&lt;br /&gt;
* STATIC_ROOT, STATIC_URL, MEDIA_ROOT et MEDIA_URL:&lt;br /&gt;
 STATIC_URL = &#039;/assets/static/&#039;&lt;br /&gt;
 STATIC_ROOT = os.path.join(BASE_DIR, &amp;quot;assets/static/&amp;quot;)&lt;br /&gt;
 MEDIA_ROOT = os.path.join(BASE_DIR, &amp;quot;assets/media/&amp;quot;)&lt;br /&gt;
 MEDIA_URL = &#039;/assets/media/&#039;&lt;br /&gt;
&lt;br /&gt;
* emails (indispensable pour être averti des erreurs 500)&lt;br /&gt;
 DEFAULT_FROM_EMAIL = &amp;quot;nom_du_binet@binets.polytechnique.fr&amp;quot;&lt;br /&gt;
 # voir https://portail.polytechnique.edu/dsi/eleves/mail-binets&lt;br /&gt;
 SERVER_EMAIL = DEFAULT_FROM_EMAIL&lt;br /&gt;
 ADMINS = [(&amp;quot;Webmaster&amp;quot;, DEFAULT_FROM_EMAIL)]&lt;br /&gt;
&lt;br /&gt;
* base de donnée : n&#039;utilisez pas sqlite ! Nous avons eu des problèmes par le passé, et les bases de données sql sont sauvegardées toutes les semaines.&lt;br /&gt;
Un snippet utilisable est :&lt;br /&gt;
 if DEBUG:&lt;br /&gt;
   DATABASES = {&lt;br /&gt;
     &#039;default&#039;: {&lt;br /&gt;
       &#039;ENGINE&#039;: &#039;django.db.backends.sqlite3&#039;,&lt;br /&gt;
       &#039;NAME&#039;: os.path.join(BASE_DIR, &#039;db.sqlite3&#039;),&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 else:&lt;br /&gt;
   DATABASES = {&lt;br /&gt;
     &#039;default&#039;: {&lt;br /&gt;
        &#039;ENGINE&#039;: &#039;django.db.backends.mysql&#039;,&lt;br /&gt;
        &#039;OPTIONS&#039;: {&lt;br /&gt;
            &#039;read_default_file&#039;: os.path.join(BASE_DIR, &#039;my.cnf&#039;),&lt;br /&gt;
        },&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Placer les mots de passe dans le fichier {{c|my.cnf}}:&lt;br /&gt;
 [client]&lt;br /&gt;
 database = NAME&lt;br /&gt;
 user = USER&lt;br /&gt;
 password = PASSWORD&lt;br /&gt;
 default-character-set = utf8&lt;br /&gt;
&lt;br /&gt;
Bien sûr il faut ajouter ce fichier dans le gitignore.&lt;br /&gt;
&lt;br /&gt;
== À chaque modification... ==&lt;br /&gt;
* du schéma SQL:&lt;br /&gt;
 python manage.py migrate&lt;br /&gt;
* des fichiers statiques:&lt;br /&gt;
 python manage.py collectstatic&lt;br /&gt;
* du code python quel qu&#039;il soit :&lt;br /&gt;
 touch /var/run/please/restart&lt;br /&gt;
Il faut attendre 1 ou deux minutes que le système enregistre la modification, quand c&#039;est fait il affiche un message dans le terminal.&lt;br /&gt;
&lt;br /&gt;
== Tester ==&lt;br /&gt;
=== Erreurs python ===&lt;br /&gt;
La commande&lt;br /&gt;
 python manage.py runserver&lt;br /&gt;
permet de vérifier qu&#039;il n&#039;y a pas d&#039;{{c|ImportError}} ou autres. Pensez à le faire dans le virtualenv.&lt;br /&gt;
=== Erreurs web ===&lt;br /&gt;
Pour checker les changements il suffit de taper l&#039;url du site pour constater en direct les changements. Si jamais il y a un souci il y a deux emplacements pour les logs : {{c|/var/log/uwsgi/nom_binet}} ou {{c|/hosting/log/nom_binet}}.&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
* Toutes les pages affichent {{c|Internal Server Error}} pas en gras : c&#039;est une erreur de {{c|uwsgi}} qui n&#039;arrive pas à :&lt;br /&gt;
** trouver ton site&lt;br /&gt;
** trouver le virtualenv&lt;br /&gt;
** une exception est levée au démarrage du serveur ({{c|ImportError}} notamment).&lt;br /&gt;
&lt;br /&gt;
Tu peux lire les logs dans {{c|/var/log/uwsgi/&amp;lt;ton binet&amp;gt;/&amp;lt;ton site&amp;gt;.log}} et vérifier où {{c|uwsgi}} va chercher ton site dans {{c|/etc/uwsgi.d/&amp;lt;ton site&amp;gt;.json}}. S&#039;il faut modifier ce dernier fichier, demande-le au BR, tu ne peux pas le faire toi même.&lt;br /&gt;
* Toutes les pages affichent {{c|Internal Server Error(500)}} en gras : c&#039;est django. Actives les mails pour avoir des détails, mais tu as probablement oublié de lancer les migrations sur une base sql vide.&lt;/div&gt;</summary>
		<author><name>Guillaume.vizier</name></author>
	</entry>
	<entry>
		<id>https://wiki-br.binets.fr/index.php?title=Authentification_Frankiz&amp;diff=8476</id>
		<title>Authentification Frankiz</title>
		<link rel="alternate" type="text/html" href="https://wiki-br.binets.fr/index.php?title=Authentification_Frankiz&amp;diff=8476"/>
		<updated>2016-09-23T13:08:05Z</updated>

		<summary type="html">&lt;p&gt;Guillaume.vizier : /* Bugs vécus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Frankiz permet à des sites externes (binets en particulier) d&#039;utiliser sa base de données pour authentifier les utilisateurs.&lt;br /&gt;
&lt;br /&gt;
Le webmaster du site en question doit auparavant faire une demande de mise en place de ce système en envoyant un mail à l&#039;équipe frankiz ([mailto:web@eleves.polytechnique.fr web@eleves.polytechnique.fr]).&lt;br /&gt;
Il doit alors donner :&lt;br /&gt;
* l&#039;url complète de la page de login de son site (plus précisément, l&#039;URL de callback)&lt;br /&gt;
* les informations auxquelles il souhaite accéder&lt;br /&gt;
* une justification de la demande (et oui, on ne partage évidemment pas notre base de données avec n&#039;importe qui !)&lt;br /&gt;
&lt;br /&gt;
Si la demande est acceptée, un admin Frankiz va alors inscrire ton site dans notre base de donnée de sites externes et générer une clé qu&#039;il va te communiquer. Cette opération se déroule via l&#039;interface d&#039;administration de frankiz. Cette clé va te permettre d&#039;authentifier les échanges d&#039;informations entre frankiz et le site externe.&lt;br /&gt;
&lt;br /&gt;
==Liste des informations disponibles==&lt;br /&gt;
&lt;br /&gt;
Tu peux demander l&#039;accès aux informations &lt;br /&gt;
&lt;br /&gt;
* names : prénom, nom, surnom, identifiant Frankiz&lt;br /&gt;
* email : adresse mail&lt;br /&gt;
* photo : URL vers la photo TOL&lt;br /&gt;
* promo : nom du premier groupe promo&lt;br /&gt;
* sport : nom de la section sportive (si applicable)&lt;br /&gt;
* rights : droits dans les groupes associés&lt;br /&gt;
* binets_admin : liste des binets dont l&#039;utilisateur est administrateur&lt;br /&gt;
&lt;br /&gt;
==Code de la page d&#039;identification en PHP==&lt;br /&gt;
Ci dessous un exemple commenté de script d&#039;authentification, à mettre sur le site externe :&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;fkz_auth.php&#039;;&lt;br /&gt;
if(!isset($_GET[&#039;response&#039;])){&lt;br /&gt;
  frankiz_do_auth();&lt;br /&gt;
}&lt;br /&gt;
$auth = frankiz_get_response();&lt;br /&gt;
// et voila !&lt;br /&gt;
// les données sont stockées dans $auth = array(key =&amp;gt; value, ...);&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Code des fonctions utilisées dans &#039;&#039;fkz_auth.php&#039;&#039;==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * Clé secrète fournie par l&#039;équipe frankiz lors de l&#039;inscription du site.&lt;br /&gt;
 * Cette clé sert à signer les requêtes et à authentifier le site.&lt;br /&gt;
 */&lt;br /&gt;
$FKZ_KEY = &amp;quot;000&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
function frankiz_do_auth(){&lt;br /&gt;
   global $FKZ_KEY;&lt;br /&gt;
  /**&lt;br /&gt;
   * Prendre le timestamp permet d&#039;éviter le rejet de la requête&lt;br /&gt;
   */&lt;br /&gt;
  $timestamp = time();&lt;br /&gt;
  /**&lt;br /&gt;
   * url de la page de login, doit correspondre *exactement* à celle entrée dans&lt;br /&gt;
   * la base de données de Frankiz (définie lors de l&#039;inscription)&lt;br /&gt;
   */&lt;br /&gt;
  $site = &#039;http://monsite/login&#039;;&lt;br /&gt;
  /**&lt;br /&gt;
   * Champ non utile pour l&#039;authentification et retransmis tel quel par frankiz. &lt;br /&gt;
   * Il est prévu pour pouvoir mettre en place un système de redirection après &lt;br /&gt;
   * authentification, vers la page à partir de laquelle le client avait tenté de se connecter.&lt;br /&gt;
   */&lt;br /&gt;
  $location  = &amp;quot;...&amp;quot; &lt;br /&gt;
  /**&lt;br /&gt;
   * Nature de la requête.&lt;br /&gt;
   * Fkz renverra ici à la fois les noms de la personne mais aussi ses droits dans différents groupes.&lt;br /&gt;
   * Il faut cependant que le site ait les droits sur les informations en question (à définir lors de son inscription).&lt;br /&gt;
   */&lt;br /&gt;
  $request = json_encode(array(&#039;names&#039;, &#039;rights&#039;, &#039;email&#039;, &#039;sport&#039;, &#039;promo&#039;, &#039;photo&#039;));&lt;br /&gt;
  &lt;br /&gt;
  $hash = md5($timestamp . $site . $FKZ_KEY . $request);&lt;br /&gt;
  &lt;br /&gt;
  $remote  = &#039;https://www.frankiz.net/remote?timestamp=&#039; . $timestamp .&lt;br /&gt;
      &#039;&amp;amp;site=&#039; . $site .&lt;br /&gt;
      &#039;&amp;amp;location=&#039; . $location .&lt;br /&gt;
      &#039;&amp;amp;hash=&#039; . $hash .&lt;br /&gt;
      &#039;&amp;amp;request=&#039; . $request;&lt;br /&gt;
   header(&amp;quot;Location:&amp;quot; . $remote);&lt;br /&gt;
   exit();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function frankiz_get_response(){&lt;br /&gt;
   global $FKZ_KEY;&lt;br /&gt;
   // Read request&lt;br /&gt;
   $timestamp = (isset($_GET[&#039;timestamp&#039;]) ? $_GET[&#039;timestamp&#039;] : 0);&lt;br /&gt;
   $response  = (isset($_GET[&#039;response&#039;])  ? urldecode($_GET[&#039;response&#039;])  : &#039;&#039;);&lt;br /&gt;
   $hash      = (isset($_GET[&#039;hash&#039;])      ? $_GET[&#039;hash&#039;]      : &#039;&#039;);&lt;br /&gt;
   $location  = (isset($_GET[&#039;location&#039;])  ? $_GET[&#039;location&#039;]  : &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
   // Frankiz security protocol&lt;br /&gt;
   if (abs($timestamp - time()) &amp;gt; 600)&lt;br /&gt;
      die(&amp;quot;Délai de réponse dépassé. Annulation de la requête&amp;quot;);&lt;br /&gt;
   if (md5($timestamp . $FKZ_KEY . $response) != $hash)&lt;br /&gt;
      die(&amp;quot;Session compromise.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   $response = json_decode($response, true);&lt;br /&gt;
   $response[&#039;location&#039;] = $location;&lt;br /&gt;
&lt;br /&gt;
   // Set empty fields&lt;br /&gt;
   $fields = array(&#039;hruid&#039;,&lt;br /&gt;
     &#039;firstname&#039;, &#039;lastname&#039;, &#039;nickname&#039;,&lt;br /&gt;
     &#039;promo&#039;, &#039;photo&#039;, &#039;location&#039;);&lt;br /&gt;
   foreach ($fields as $k) {&lt;br /&gt;
      if (!isset($response[$k]))&lt;br /&gt;
      $response[$k] = &#039;&#039;;&lt;br /&gt;
   }&lt;br /&gt;
   return $response;&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Avec Django==&lt;br /&gt;
L&#039;interfaçage avec Django n&#039;est pas trivial, pour le faire proprement il faudrait coder un backend d&#039;authentification. En attendant, le code ci dessous est un peu sale mais marche. Il sauve l&#039;username frankiz dans la session, ce qui est raisonnablement safe normalement.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
def logout(request):&lt;br /&gt;
    del request.session[&amp;quot;username&amp;quot;]&lt;br /&gt;
    request.session.modified = True&lt;br /&gt;
    return redirect(&amp;quot;/&amp;quot;) &lt;br /&gt;
 &lt;br /&gt;
def fkz_answer(request): &lt;br /&gt;
    if not &amp;quot;timestamp&amp;quot; in request.GET.keys() or not &amp;quot;response&amp;quot; in request.GET.keys() or not &amp;quot;hash&amp;quot; in request.GET.keys(): &lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
    response = request.GET.get(&amp;quot;response&amp;quot;)&lt;br /&gt;
    ts = request.GET.get(&amp;quot;timestamp&amp;quot;)&lt;br /&gt;
    h = request.GET.get(&amp;quot;hash&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if abs(int(timestamp()) - int(ts)) &amp;gt; 600:&lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if hashlib.md5(ts + FKZ_KEY + response).hexdigest() != h:&lt;br /&gt;
        return redirect(&amp;quot;/login_required/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    data = json.loads(response)&lt;br /&gt;
    request.session[&#039;username&#039;] = data[&#039;hruid&#039;]&lt;br /&gt;
    return redirect(&amp;quot;/&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def fkz_do_login(request):&lt;br /&gt;
    ts = timestamp()&lt;br /&gt;
    page = &amp;quot;http://***/fkz_answer/&amp;quot;&lt;br /&gt;
    r = json.dumps([&amp;quot;names&amp;quot;, &amp;quot;email&amp;quot;])&lt;br /&gt;
    h = hashlib.md5(ts + page + FKZ_KEY + r).hexdigest()&lt;br /&gt;
    return redirect(&amp;quot;http://www.frankiz.net/remote?&amp;quot;+urlencode([(&#039;timestamp&#039;,ts),(&#039;site&#039;,page),(&#039;hash&#039;,h),(&#039;request&#039;,r)]))&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Avec Drupal==&lt;br /&gt;
&lt;br /&gt;
L&#039;implémentation de l&#039;authentification avec un CMS comme Drupal n&#039;est pas forcément évidente. Si vous avez une question, vous pouvez contacter [mailto:antoine.sauvage@polytechnique.edu Antoine Sauvage]&lt;br /&gt;
&lt;br /&gt;
==Bugs vécus==&lt;br /&gt;
&lt;br /&gt;
Si l&#039;authentification ne fonctionne pas sur certains navigateurs, vérifier les variables $_GET car elles sont peut être doublement encodées. Dans ce cas, soit refaire &#039;&#039;&#039;urldecode&#039;&#039;&#039;, soit un &lt;br /&gt;
 $s = str_replace(&#039;%22&#039;,&#039;&amp;quot;&#039;,$s);&lt;br /&gt;
Si il y a un problème avec les encodages en \u&#039;&#039;machinchose&#039;&#039; pour les caractères accentués, voila une fonction qui peut vous servir (reconversion en UTF-8) :&lt;br /&gt;
 function jsonClean($s) {&lt;br /&gt;
   return preg_replace(&amp;quot;/\\\\u([a-f0-9]{4})/e&amp;quot;, &amp;quot;iconv(&#039;UCS-4LE&#039;,&#039;UTF-8&#039;,pack(&#039;V&#039;, hexdec(&#039;U$1&#039;)))&amp;quot;,$s);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:Dev]]&lt;/div&gt;</summary>
		<author><name>Guillaume.vizier</name></author>
	</entry>
</feed>