Запретить пользователям доступ к данным другого пользователя при вводе слаг в URL

Если пользователь 1 создал этот билет: mywebsite/manager/tickets/ticket-from-user-1/

И пользователь 2 создает это: mywebsite/manager/tickets/ticket-from-user-2/

Как я могу запретить пользователю 1 доступ к заявке от пользователя 2 или других пользователей, введя его в URL?

views.py

class TicketDisplay(LoginRequiredMixin, DetailView):
    model = Ticket
    template_name = 'ticket_detail.html'
    context_object_name = 'ticket'
    slug_field = 'slug'

    def get_context_data(self, **kwargs):
        context = super(TicketDisplay, self).get_context_data(**kwargs)
        context['form_add_comment'] = CommentForm()
        return context

url.py

url(r'^manager/tickets/(?P<slug>[-\w]+)/$',views.TicketDetail.as_view(), name='ticket_detail')

2 ответа

Решение

Я недавно реализовал эту функциональность в проекте. Это можно сделать с помощью автоматически сгенерированных uuid. Django имеет встроенное поле модели для этого, или вы можете использовать поле slug и задать ему значение по умолчанию. Вот быстрый пример.

В файле models.py импортируйте библиотеку uuid, а затем установите значение по умолчанию для вашего поля slug равным uuid.uuid4.

models.py:

import uuid

class Ticket(models.Model):
    uuid = models.SlugField(default=uuid.uuid4, editable=False)
    ...

В urls.py просто используйте поле uuid, как будто это pk. Что-то вроде этого:

url(r'^manager/tickets/(?P<uuid>[0-9a-z-]+)/?$', TicketDetail.as_view(), name='ticket-detail'),

В ваших подробностях, обновлении и удалении представлений вам необходимо убедиться, что эти два атрибута установлены и установлены таким образом, чтобы Django знал, какое поле использовать как слаг:

slug_field = 'uuid'
slug_url_kwarg = 'uuid'

Затем в ваших шаблонах и всякий раз, когда вам нужно получить объект для kwargs, просто используйте uuid вместо pk.

Обратите внимание, что в дополнение к этому вы также должны делать все возможное с разрешениями, чтобы запретить пользователям видеть другие страницы. Возможно, вы сможете заблокировать определенные учетные записи от просмотра сведений о других людях. Например, вы могли бы написать миксин разрешений, чтобы проверить, соответствует ли request.user объекту, который обрабатывает представление.

tldr Это предполагает, что у вас есть какое-то отношение к пользователю на вашем Ticket модель:

class SameUserOnlyMixin(object):

    def has_permissions(self):
        # Assumes that your Ticket model has a foreign key called user.
        return self.get_object().user == self.request.user

    def dispatch(self, request, *args, **kwargs):
        if not self.has_permissions():
            raise Http404('You do not have permission.')
        return super(SameUserOnlyMixin, self).dispatch(
            request, *args, **kwargs)

Наконец, придерживайтесь этого вида так:

class TicketDisplay(LoginRequiredMixin, SameUserOnlyMixin, DetailView):
    ...

Вам нужно сделать так, чтобы у пользователя 1 было что-то, что пользователь 2 не может имитировать.

Предпочтительным способом будет использование существующих методов аутентификации и проверка, разрешено ли пользователю, обращающемуся к странице.

Если у вас нет регистрации на вашем сайте, вы можете сгенерировать случайную строку - secret - и сохраните это с вопросом. Если "пользователь" имеет это secret тогда ему позволено

Эта секретная строка может быть сохранена в cookie или включена в URL.

Хранение его в cookie-файле имеет недостаток: если cookie-файл потерян, никто не сможет получить доступ к странице. Также пользователь не может получить к нему доступ из другого браузера.

Включение его в URL-адрес имеет еще один недостаток: если кто-то еще видит ссылку, он также может получить доступ к этой странице. Это может быть плохо, если программное обеспечение пользователя автоматически сообщает о посещениях, которые он посещает.

Объединение этих подходов имеет оба недостатка.

Другие вопросы по тегам