2013-08-13 4 views
0

Проект Django, над которым я сейчас работаю, - это веб-сайт, к которому следует обращаться из локальной сети и Интернета. А часть контента должна быть доступна анонимным пользователям только в том случае, если вы посещаете сайт из локальной сети (в основном это тест на IP-адрес), тогда как аутентифицированные пользователи имеют доступ ко всему контенту.Разный тип анонимных пользователей с Django

Я, хотя про проверку IP as described here, но мне кажется довольно плохо проверять ip каждый раз, когда пользователь загружает страницу.

Есть ли способ очистить данные пользователя даже от анонимного пользователя? Было бы неплохо просто использовать декоратор, например, @login_required, но который перенаправлялся бы только в том случае, если у анонимного пользователя есть внешний IP-адрес.

+1

Разве это не то, что [сеансы] (https://docs.djangoproject.com/en/dev/topics/http/sessions/)? –

ответ

2

Фактически, проверка ip на каждом запросе кажется мне одним из самых быстрых доступных методов. Учтите, что ip уже загружен в память по каждому запросу, все, что вам нужно сделать, это простой поиск в словарях и сравнение с условным расщеплением строк/дополнительным исканием. По сравнению с тем, что происходит даже на самых простых просмотрах страниц, влияние производительности полностью пренебрежимо и сопоставимо с последствиями использования сеансов или любого другого механизма для сохранения ip.

Вы можете написать свою собственную функцию декоратора с помощью user_passes_test:

from django.contrib.auth.decorators import user_passes_test 
from django.utils.decorators import available_attrs 
from functools import wraps 

LOCAL_IPS = (
    '127.0.0.1', 
    'other_ip', 
    'etc.', 
) 

def is_local_request(request): 
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') 
    if x_forwarded_for: 
     ip = x_forwarded_for.split(',')[0] 
    else: 
     ip = request.META.get('REMOTE_ADDR') 
    return ip in LOCAL_IPS 

def local_ip_required(view_func): 
    def wrapped_view(request, *args, **kwargs): 
     if not is_local_request(request): 
      raise Http404 # or PermissionDenied or redirect 
     return view_func(request, *args, **kwargs) 
    return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view) 

Тогда просто использовать @local_ip_required. Обратите внимание, что эта реализация предотвратит доступ анонимных и зарегистрированных пользователей к просмотру из внешнего местоположения.

+0

Спасибо, я не понимал, что было так легко определить декораторов, я должен был бы легко адаптировать его к '@ authentication_or_local_ip_required'. Небольшая деталь, в моем случае, локальные ips определяются как набор диапазонов, таких как '192.168.1. *', Есть ли простой ярлык для его проверки или я должен выполнять сравнения строк? – Levans

+0

Существует несколько [пакетов инструментов IP] (https://code.google.com/p/netaddr/wiki/YetAnotherPythonIPModule). Ищите те, которые поддерживают диапазоны и предоставляют реализацию '__contains__' и выбирают. Если вы знакомы с netmasks: это то, что большинство пакетов, похоже, используют вместо подстановочных знаков. Если вы не знакомы: вы должны быть: P Но по крайней мере [python-iptools] (https://code.google.com/p/python-iptools/) поддерживает диапазоны в форме '(('192.168. 1.0 ',' 192.168.1.255 '),) '. – knbk