Мен әзірлеп жатқан ресурстардың бірінде пайдаланушының осы медиа мазмұнға кіру құқығын тексере отырып, медиа-контентке қорғалған қолжетімділікті қосу қажеттілігі туындады. Қарапайым сөзбен айтқанда, пайдаланушы nginx статикалық мазмұн ретінде қызмет ететін фотосуретті көре алады.
Шын мәнінде, nginx және Django жағдайында бәрі бір қарағанда қарапайым болып көрінеді.
Мұны фотосуретті жүктеп салу және жүктеп салу мысалы арқылы қарастырайық.
Фотосуретпен жұмыс істеу алгоритмі
- Фотосуретті арнайы қорғалған каталогқа жүктеп салу
- Фотосуретке тікелей url арқылы немесе веб-сайт бетінде фотосуретті алу әрекеті (мысалы, img тегі)
- Фотосурет рұқсаттарын тексеру
- Nginx жүйесінде сервердегі ішкі қорғалған каталогқа қайта бағыттауды жасау
- Фотосуретті қабылдау
Барлығы қарапайым болып көрінеді, бірақ енді бұл үшін не қажет екенін көрейік.
settings.py
Сайттың джанго конфигурация файлын баптайық. Әдетте, мультимедиалық мазмұнды жүктеп алу және оған nginx арқылы автоматты түрде қызмет көрсету үшін параметрлерде ұқсас нәрсе жазылған.
MEDIA_ROOT = BASE_DIR.parent / 'media' MEDIA_URL = '/media/'
Дегенмен, бұл жолы біз әрқашан қорғалған деп атайтын арнайы қорғалған каталогты қолданамыз.
MEDIA_ROOT = BASE_DIR.parent / 'protected' MEDIA_URL = '/media/'
Осылайша, біз сыртқы кеңістікте «медиа» бар, ал сервердің қараңғы залдарында «қорғалған» дейміз.
Мұндай код келесі каталог құрылымына сәйкес келуі мүмкін.
- /home/www/django_project_root_folder - бұл жоба, статикалық және бал каталогтары, сондай-ақ виртуалды орта орналасқан негізгі каталог.
- /home/www/django_project_root_folder/protected - қорғалған медиа каталогы
- /home/www/django_project_root_folder/static - статикалық мазмұны бар каталог
- /home/www/django_project_root_folder/django_project - сіздің джанго қолданбаңыз
- /home/www/django_project_root_folder/python_venv - виртуалды орта
Маған қазір бұл құрылым ұнайды, өйткені егер python нұсқасы өзгерсе, яғни виртуалды орта жаңартылса, сіз жай ғана жаңа ортаны инициализациялауға және конфигурациядағы бірнеше жолды өзгертуге болады, осылайша сайт қолданбасы жаңа виртуалды ортадан іске қосылады. . Бұл жағдайда жоба репозиторийіне де, статикалық файлдарға да, медиа мазмұнына да әсер етпейді.
nginx конфигурациясы
Мен қорғалған каталогқа nginx қатынасын орнатуға тікелей жауапты конфигурацияның шағын бөлігін беремін.
server { # Other code location /protected/ { internal; root /home/www/django_project_root_folder/; expires 30d; } }
Бұл код арқылы біз қорғалған каталогтың қай жерде орналасқанын және оның ішкі екенін ғана көрсетеміз, яғни пайдаланушы оның мазмұнын арнайы рұқсатсыз жай ғана қабылдамайды.
Фотосуреттерді жүктеп салу
Фотосуреттермен жұмыс істеу үшін мен қазір бұл деректер үлгісін қолданамын, әрине, нақты жоба үшін модификациялармен, бірақ негізі бірдей
# -*- coding: utf-8 -*- import os import uuid from django.contrib.gis.db import models from django.db.models.signals import post_delete from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ from photo.fields import WEBPField from photo.managers import PhotoManager def image_folder(instance, filename): return 'photos/{}.webp'.format(uuid.uuid4().hex) class Photo(models.Model): class Meta: verbose_name = _('Photo') verbose_name_plural = _('Photos') created_at = models.DateTimeField(verbose_name=_('Created at'), auto_now_add=True) updated_at = models.DateTimeField(verbose_name=_('Updated at'), auto_now=True) height = models.IntegerField(verbose_name=_('Height'), default=0, blank=True, null=True) width = models.IntegerField(verbose_name=_('Width'), default=0, blank=True, null=True) image = WEBPField( verbose_name=_('Image'), upload_to=image_folder, height_field='height', width_field='width', ) def filename(self): return os.path.basename(self.image.name) @receiver(post_delete, sender=Photo) def auto_delete_image_on_delete(sender, instance, **kwargs): if instance.image: if os.path.isfile(instance.image.path): os.remove(instance.image.path)
Мұнда арнайы өріс WEBPField пайдаланылады, ол туралы мен айтқанмын. Бұл кескінді жылдам webp пішіміне түрлендіретін өріс. Сондай-ақ серверден фотосуреттерді автоматты түрде жою коды бар. Бірақ бұл ең маңызды нәрсе емес.
Ең бастысы - бұл функция
def image_folder(instance, filename): return 'photos/{}.webp'.format(uuid.uuid4().hex)
Бұл функция файл атауын жасайды және қорғалған каталогқа қатысты файлды серверде сақтау орнын көрсетеді.
Нәтижесінде фотосурет келесі жолда сақталады
/home/www/django_project_root_folder/protected/photos/0aec484a6ff246d7ad5eb1b06c0a698e.webp
Бұл жағдайда үлгідегі img тегінің коды келесідей болады:
<img src="{{ photo.image.url }}"/>
Ал нәтиже келесідей болады
<img src="/media/photos/0aec484a6ff246d7ad5eb1b06c0a698e.webp"/>
urls.py
Мазмұнға қол жеткізу үшін url менеджерін көрсетуден бастаймын
# -*- coding: utf-8 -*- from django.urls import path from photo.views import photo_access urlpatterns = [ path('media/photos/<str:path>', photo_access, name='photo'), ]
Көріп отырғаныңыздай, мұнда img тегінің нәтижесіне сәйкес келетін url бар.
Фотосуретке қол жеткізу функциясы
Енді ең қызығы - қорғалған мазмұнға қол жеткізу қалай жүзеге асырылады
# -*- coding: utf-8 -*- from django.http import HttpResponse, HttpResponseForbidden from photo.models import Photo from utils.shortcuts import get_object_or_none def photo_access(request, path): def create_x_accel_redirect(path): response = HttpResponse() # Content-type will be detected by nginx del response['Content-Type'] response['X-Accel-Redirect'] = '/protected/photos/' + path return response photo = get_object_or_none(Photo, image='photos/' + path) if photo is None: return HttpResponseForbidden('Not authorized to access this media.') # Some another check code if condition is True: return create_x_accel_redirect(path) if request.user.is_authenticated and request.user.is_staff: return create_x_accel_redirect(path) return HttpResponseForbidden('Not authorized to access this media.')
Бұл функцияда біз пайдаланушының ресурс әкімшілігінің уәкілетті өкілі екенін және фотообъектінің бар-жоғын тексереміз. Сондай-ақ, сіз өзіңізге ұнайтын кез келген басқа шарттарды қоса аласыз.
Егер олар орындалса, create_x_accel_redirect функциясын пайдаланып, nginx ішіндегі сұрауды кескінге қайта бағыттайтын директиваны қосамыз.
Яғни,
/media/photos/0aec484a6ff246d7ad5eb1b06c0a698e.webp
орнына
/protected/photos/0aec484a6ff246d7ad5eb1b06c0a698e.webp
және direct-cc-redirect.X сұрауын қайта бағыттау** ауыстырамыз.
Осылайша, nginx қорғалған каталогтағы мазмұнды медиа url арқылы қызмет етеді.
X-Accel-Redirect директивасы туралы толығырақ ақпаратты ресми nginx wiki сайтынан табуға болады