web-dev-qa-db-fra.com

Django [Errno 13] Autorisation refusée: '/ var/www/media/animals/user_uploads'

Je développe une API Django qui s'exécutera sur Apache2 via WSGI sur un serveur exécutant Ubuntu. 

Les utilisateurs pourront télécharger des images qu'ils prennent sur le serveur à l'aide d'une demande POST. L'API traite cette demande et tente ensuite d'écrire l'image dans /var/www/media/animals/user_uploads/<animal_type>/<picture_name>.jpg. S'il n'y a pas de répertoire /var/www/media/animals/user_uploads/<animal_type>/, il le créera. 

Lors des tests pendant le développement, tout allait bien, à la fois sous Windows et Scientific Linux. Lors du test sur le serveur de déploiement, je reçois cette erreur:

Django Error

D'après ce que j'ai compris, le serveur Apache2 fonctionne avec l'utilisateur www-data. Dans mon cas, exécuter cat /etc/passwd pour obtenir la liste des utilisateurs, voici ce que je reçois pour www-data:

www-data: x: 33: 33: www-data:/var/www:/bin/sh

Je suppose que cela signifie que www-data a accès à tout ce qui se trouve dans /var/www/. J'ai essayé: 

chmod 777 -R médias

Cela a fonctionné mais c'est évidemment un très mauvais moyen de résoudre ce problème. Y a-t-il une meilleure façon de résoudre ce problème?

Ceci est mon wsgi.py:

import os, sys
os.environ.setdefault("Django_SETTINGS_MODULE", "serengeti.settings")
sys.path.append('/serengeti/Django/serengeti')
sys.path.append('/serengeti/Django')

from Django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

J'ai ceci dans mon fichier settings.py:

MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = os.path.join(BASE_DIR,'/media/')

Mon vhost.conf contient ceci:

Alias /media/ /var/www/media/
16
Vlad Schnakovszki

Je l'ai résolu moi-même à la fin. 

En cours d'exécution sur les machines de développement, j'utilise en fait les privilèges de mon utilisateur actuel. Toutefois, lors de l’exécution sur le serveur de déploiement, j’exécute en fait wsgi, ce qui signifie qu’il fonctionne avec les privilèges de www-data.

www-data n'est ni le propriétaire ni le groupe d'utilisateurs qui possèdent /var/www. Cela signifie que www-data est traité en tant que other et que les autorisations sont définies sur autres.

La solution BAD à cela serait la suivante:

Sudo chmod -R 777 /var/www/

Cela donnerait à tout le monde un accès complet à tout ce qui se trouve dans /var/www/, ce qui est une très mauvaise idée .

Une autre solution BAD serait de faire:

Sudo chown -R www-data /var/www/

Cela changerait le propriétaire en www-data, ce qui ouvre des vulnérabilités de sécurité .

La solution BIEN serait:

Sudo groupadd varwwwusers
Sudo adduser www-data varwwwusers
Sudo chgrp -R varwwwusers /var/www/
Sudo chmod -R 760 /var/www/

Cela ajoute www-data au groupe varwwwusers, qui est ensuite défini comme groupe pour /var/www/ et tous ses sous-dossiers. chmod donnera les autorisations de lecture, d’écriture et d’exécution au propriétaire, mais le groupe ne sera pas en mesure d’exécuter un script potentiellement chargé là-bas si, par exemple, le serveur Web a été piraté. 

Vous pouvez le définir sur 740 pour le rendre plus sûr, mais vous ne pourrez pas utiliser la fonctionnalité Django'scollectstatic, tenez-vous-en à 760 si vous n'êtes pas très sûr de ce que vous faites.

49
Vlad Schnakovszki

J'ai eu un problème similaire dans Django 1.10, et cette page était le premier résultat de Google, mais la solution acceptée n'a pas résolu mon problème. Avec un répertoire 'MEDIA' situé à la racine de votre projet pour stocker les fichiers, il vous suffisait de définir:

MEDIA_ROOT = os.path.join (BASE_DIR, 'MEDIA')

et puis j'ai arrêté de recevoir l'erreur. J'avais essayé un certain nombre de variantes avant de constater que cela fonctionnait. 

7
Nic Scozzaro

Pour savoir à quel utilisateur vous êtes connecté:

$ whoami
ubuntu

Et en ajoutant à votre solution, si vous utilisez une instance AWS, vous devez ajouter votre utilisateur au groupe pour pouvoir accéder à ce dossier:

Création d'un groupe pour les utilisateurs de services Web (varwwwusers)

$ Sudo groupadd varwwwusers

Changer le dossier www et le faire appartenir à varwwwusers

$ Sudo chgrp -R varwwwusers /var/www/

www-data est le serveur qui fait les requêtes Django, ajoutez-le au groupe

$ Sudo adduser www-data varwwwusers

Changer la politique de dossier

$ Sudo chmod -R 770 /var/www/

Ajoutez ubuntu au groupe de varwwwusers

$ usermod -a -G varwwwusers ubuntu

J'espère que cela t'aides!

4
Abdulla AlKhenji

La solution à ce problème lorsqu’il s’agit du serveur de production consiste à utiliser collectstatic, comme il a déjà été mentionné, qu’il a utilisé et résolu ou à accorder des autorisations aux dossiers. Toutefois, si votre solution se trouve dans un environnement local, vous pouvez l’acquérir en configurant le répertoire local MEDIA dans le fichier settings.py qui agit sur le serveur local.

Donc, ajouterait ces deux lignes dans le fichier de configuration local comme indiqué par @Nic Scozzaro:

MEDIA_ROOT = os.path.join (BASE_DIR, 'media')
STATIC_ROOT = os.path.join (BASE_DIR, 'static')

Après la configuration, redémarrez les services pour appliquer les correctifs.

0
Lucas Coelho