2012-09-12 17 views
8

Mam małą aplikację Django z widokiem, który chcę ograniczyć do niektórych użytkowników. Każda osoba z określonej sieci powinna mieć możliwość wyświetlenia tego widoku bez dalszego uwierzytelniania, wyłącznie na podstawie adresu IP. Osoby spoza tego zakresu adresów IP powinny zostać poproszone o podanie hasła i uwierzytelnione w stosunku do domyślnego zarządzania użytkownikami Django.Uwierzytelnianie za pomocą adresu IP w Django

Zakładam, że muszę napisać niestandardowy backend uwierzytelniający, ale dokumentacja myli mnie, ponieważ funkcja authenticate() wydaje się oczekiwać kombinacji nazwy użytkownika/hasła lub tokena. Nie jest dla mnie jasne, w jaki sposób uwierzytelniać przy użyciu adresów IP tutaj.

Jaki byłby właściwy sposób implementacji uwierzytelniania opartego na adresie IP w Django? Wolałbym używać jak najwięcej istniejących funkcji bibliotecznych dla kodu związanego z bezpieczeństwem, zamiast samemu go pisać.

Odpowiedz

3

Nie trzeba pisać backendu uwierzytelniającego w przypadku, który napisałeś. Wpisanie dyspozytora opartego na IP w warstwie oprogramowania pośredniego będzie prawdopodobnie wystarczające. Jeśli adres URL Twojej aplikacji jest/są dopasowane, process_request powinien sprawdzić uwierzytelnionego użytkownika django i dopasować go do białej listy.

6

Można również napisać mały dekorator do tego celu:

def login_by_ip(view_func): 
    def authorize(request, *args, **kwargs): 
     user_ip = request.META['REMOTE_ADDR'] 
     for ip in allowedIps.allowedIps: 
      authenticated_by_ip = re.compile(ip).match(user_ip) 
      if authenticated_by_ip: 
       return view_func(request, authenticated_by_ip, *args, **kwargs) 
     return HttpResponseRedirect('/redirect/path/') 
    return authorize 

allowedIps jest w moim przypadku plik (allowedIps.py), który przechowuje regexes dla dozwolonych adresów IP w krotce jak ten:

allowedIps = ('^XXX\.XXX\..+\..+$','^XXX\.XXX\.XXX\..+$', '^XXX\.XXX\.XXX\.XXX$') 

Mam nadzieję, że to może pomóc lub dać pomysł. Uwaga: jeśli zwrócisz uwierzytelnione_by_ip do dekorowanego widoku, twój widok będzie musiał zaakceptować ten parametr, możesz go także ominąć, jeśli go nie potrzebujesz. Możesz również zdefiniować wyrażenia dokładniej, aby akceptować tylko cyfry do trzech.

1
def login_by_id(request): 
    ip = request.META['REMOTE_ADDR'] 
    try: UserProfile.objects.get(allow_ip=id) 
    except UserProfile.DoesNotExist: return HttpResponseRedirect('././') 
    else: 
     # auth here 

Trzeba allow_ip w ciebie UserProfile modelu, który zaoszczędzić na rejestrację lub zmian na stronie użytkownika edycji

9

Istnieją dwa odpowiednie podejście do tego rodzaju uwierzytelniania:

  • Jako Dekorator: jeśli niektóre widoki (ale nie wiele z nich) wymagają tego czeku, to lepiej napisać do tego dekoratora (coś takiego, jak napisał @Jingo)
  • Jako oprogramowanie pośrednie:, jeśli to sprawdzenie powinno być wykonane przez wszystkie (lub wiele) widoków, zamiast używania dekoratora, lepszym rozwiązaniem jest napisanie middleware.

Próbkę middleware może być coś takiego:

ALLOWED_IP_BLOCKS = [......] 

class NeedToLoginMiddleware(object): 
    def process_request(self, request): 
     ip = request.META['REMOTE_ADDR'] 
     if not ip in ALLOWED_IP_BLOCKS: #ip check 
      if not request.user.is_authenticated(): #if ip check failed, make authentication check 
       return HttpResponseRedirect(...) 
    return None 
  • Można dokonać sprawdzenia ip podstawie listy lub regex jak wspomniano @Jingo.
  • Jeśli używasz uwierzytelniania django i REMOTE_ADDR nie znajduje się na liście ALLOWED_IP_BLOCKS, możesz użyć is_authenticated, aby sprawdzić, czy powiązany użytkownik zalogował się, czy nie.Jednak w przypadku używania oprogramowania warstwy pośredniej w wersji is_autheticated, niestandardowe oprogramowanie pośredniczące musi zostać umieszczone poAuthenticationMiddleware, ponieważ ustawienie request.user jest ustawione na tym poziomie.

    MIDDLEWARE_CLASSES = (
        ... 
        'django.contrib.auth.middleware.AuthenticationMiddleware', 
        'path.to.my.NeedToLoginMiddleware', 
        ... 
    ) 
    
    • Jeśli kilka poglądy nie wymagają tego uwierzytelniania, można zrobić listę wyjątkowych adresów URL i uzyskać adres URL żądania od request.path i sprawdzić, czy adres URL żądania uwierzytelniania wymaga wyboru/IP.

Więcej informacji o custom middleware classes

+1

Umieszczenie 'ALLOWED_IP_BLOCKS' do * settings.py *, a dostępu do niego z' 'settings.ALLOWED_IP_BLOCKS' (potrzebuje od importu django.conf Settings') pozwoliłoby ładniejszy konfiguracja, – luckydonald

1

IMO, rozwiązując z Django to jest w porządku, jeśli jest to mały niewykonanie krytycznym miejscu.

Lepiej utrzymywać nieautoryzowanych użytkowników w pełni za pomocą usługi Apache lub Nginx. Na przykład, w Nginx mam te linie w mojej konfiguracji site:

include allowed_ips.conf; 
deny all; 
error_page 403 forbidden.html; 

allowed_ips.conf znajduje się w/etc/nginx i wygląda na (coś) tak:

allow 110.222.333.222; # J Bloggs (sys admin) 
allow 777.222.0.0/16; # Government owned 
... 

Wierzę, że to jest lepsze ponieważ stosunkowo powolne procesy Django nigdy nie zostaną dotknięte zablokowanymi adresami IP. Jest to istotne, jeśli blokujesz boty lub inne zakresy adresów krajowych ze względu na wydajność lub bezpieczeństwo.

3

Możesz wypróbować ten dekorator. Ja testowałem jego pracy grzywny:

allowedIps = ['129.0.0.1', '127.0.0.1'] 
def allow_by_ip(view_func): 
    def authorize(request, *args, **kwargs): 
     user_ip = request.META['REMOTE_ADDR'] 
     for ip in allowedIps: 
      if ip==user_ip: 
       return view_func(request, *args, **kwargs) 
     return HttpResponse('Invalid Ip Access!') 
    return authorize 
Powiązane problemy