Запретить пользователям доступ к данным другого пользователя при вводе слаг в 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-адрес имеет еще один недостаток: если кто-то еще видит ссылку, он также может получить доступ к этой странице. Это может быть плохо, если программное обеспечение пользователя автоматически сообщает о посещениях, которые он посещает.
Объединение этих подходов имеет оба недостатка.