Django Rest Framework и React Front End. Как запретить неавторизованным пользователям просматривать личные изображения, если они получают URL-адрес изображения? - PullRequest
2 голосов
/ 30 апреля 2020

Насколько я понимаю, на обычном веб-сайте React все носители будут передаваться с того же сервера, что и внешние файлы (HTML, CSS и Javascript).

REST Бэкэнд API будет предоставлять только ссылки на места хранения этих изображений, и он будет обслуживаться и отображаться внешним интерфейсом.

Проблема в том, что эти изображения являются частными, и только один пользователь должен их видеть. Если кто-то заполучит URL-адрес изображения и откроет его, он сможет увидеть его.

Как современные веб-сайты решают эту проблему? Каков рабочий процесс между Django и React для обеспечения безопасности и конфиденциальности изображений пользователя?

Ответы [ 3 ]

2 голосов
/ 03 мая 2020

Это больше похоже на добавление к ответу другого человека относительно X-Accel. X-Accel решил первую половину проблемы, то есть привратника для ссылок.

Другая половина проблемы заключается в том, что иногда вы не сможете аутентифицировать пользователей, которые легко, например, в типичной настройке React / DRF, вы будете использовать JWT, и не сможете контролировать какие заголовки браузер отправит на ваш сервер. У вас будут следующие опции:

  1. Вам нужно будет либо выбрать использование аутентификации на основе cook ie

  2. Реализовать собственный механизм аутентификации в ссылке на изображение, аналогично тому, как работает предварительно подписанный URL AWS S3. Самый простой способ сделать это - сгенерировать URL к изображению в соответствии с модулем Nginx secure_link. Ссылка: https://www.nginx.com/blog/securing-urls-secure-link-module-nginx-plus/

Я выбираю метод № 2, имея пользовательское поле / класс сериализатора (.ie SecuredFilePathSerializer) и использую его вместо FilePathField.

1 голос
/ 03 мая 2020
Step 1: All requests for media should go throught a specific view

Edit file myproject/urls.py and add:

from myproject.views import media_access

urlpatterns = [
    ...,
    url(r'^media/(?P<path>.*)', media_access, name='media'),
]


Step 2: Add the view and check access

Add the following view in myproject/views.py:

from django.http import HttpResponse
from django.http import HttpResponseForbidden

def media_access(request, path):
    """
    When trying to access :
    myproject.com/media/uploads/passport.png

    If access is authorized, the request will be redirected to
    myproject.com/protected/media/uploads/passport.png

    This special URL will be handle by nginx we the help of X-Accel
    """

    access_granted = False

    user = request.user
    if user.is_authenticated():
        if user.is_staff:
            # If admin, everything is granted
            access_granted = True
        else:
            # For simple user, only their documents can be accessed
            user_documents = [
                user.identity_document,
                # add here more allowed documents
            ]

            for doc in user_documents:
                if path == doc.name:
                    access_granted = True

    if access_granted:
        response = HttpResponse()
        # Content-type will be detected by nginx
        del response['Content-Type']
        response['X-Accel-Redirect'] = '/protected/media/' + path
        return response
    else:
        return HttpResponseForbidden('Not authorized to access this media.')


Here the important part is about the variable user_documents. It should contain reference to all files the user has access. In my case I extended the User model to add a field identity_document that why I can access it here.

In this media_acces view, you can implement any authorization logic.


Step 3: Configure nginx

Here is a full example of nginx configuration. The important part is about location /protected/. We suppose that Django is available with Gunicorn on port 8080 for example.

upstream myprojectapp {
  server localhost:8080;
}

server {
    listen 80;

    server_name myproject.com;

    server_name_in_redirect on;
    error_log /var/log/nginx/myproject-error.log crit;
    access_log  /var/log/nginx/myproject-access.log custom_combined;

    root /path/to/my/django/project/static;

    location ^~ /static/ {
        alias /path/to/my/django/project/static/;
    }

    location /protected/ {
        internal;
        alias /path/to/my/django/project/;
    }

    location / {
        include proxy_params;
        proxy_pass http://myprojectapp;
        proxy_buffering off;
    }

}

You can notice there is no location ^~ /media/ that's because this URL is handle by django.
0 голосов
/ 05 мая 2020

На самом деле, перед тем, как конечная точка REST API обслуживает URL изображений, запрос и ответ конечной точки могут быть надлежащим образом авторизованы с использованием инфраструктуры авторизации Django REST Framework.

Кроме того, вы можете написать свои собственные Django промежуточные программы [HTTP-хуки] для желаемой конечной цели.

Промежуточные программы могут настраивать поведение запросов-ответов HTTP в соответствии с вашими потребностями.

...