2012-09-12 15 views
8

Ho una piccola applicazione Django con una vista che voglio limitare a determinati utenti. Chiunque provenga da una rete specifica dovrebbe essere in grado di vedere quella vista senza alcuna ulteriore autenticazione, basata solo sull'indirizzo IP. A chiunque altro al di fuori di questo intervallo IP dovrebbe essere chiesta una password e autenticato rispetto alla gestione utente Django predefinita.Autentica per indirizzo IP in Django

Suppongo di dover scrivere un backend di autenticazione personalizzato per questo, ma la documentazione mi confonde poiché la funzione authenticate() sembra aspettarsi una combinazione nome utente/password o un token. Non mi è chiaro come eseguire l'autenticazione utilizzando gli indirizzi IP qui.

Quale sarebbe il modo corretto di implementare l'autenticazione basata su indirizzo IP in Django? Preferirei utilizzare quante più funzioni di libreria esistenti possibili per il codice relativo alla sicurezza invece di scriverlo tutto da solo.

risposta

3

Non è necessario scrivere un back-end di autenticazione per il caso d'uso che è stato scritto. Sarà sufficiente scrivere un dispatcher basato su IP nel livello middleware

Se l'URL della tua app è/sono abbinato, process_request dovrebbe verificare la presenza di un utente django autenticato e associare tale utente a una lista bianca.

6

È possibile anche scrivere un piccolo decoratore per questo scopo:

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 è nel mio caso un file (allowedIps.py) che memorizza le regex per gli IP consentiti in una tupla come questo:

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

Spero che questo possa aiutare o dare un'idea. Nota: se restituisci authenticated_by_ip alla vista decorata, la tua vista dovrà accettare quel parametro, puoi anche solo ometterlo, se non ne hai bisogno. È inoltre possibile definire le espressioni regolari in modo più preciso per accettare solo cifre fino a tre.

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 

È necessario allow_ip in te modello UserProfile, che risparmiare sulle registrazione o modifiche sulla pagina utente modifica

9

Ci sono due approcci idonei per questo tipo di autenticazione:

  • Come Decorator: se alcuni dei punti di vista (ma non molti) richiedono questo controllo, allora è meglio scrivere un decoratore per questo (qualcosa come aveva scritto @Jingo)
  • Come middleware: se tale controllo deve essere eseguito da tutte (o molte) visualizzazioni, invece di utilizzare un decoratore, la scrittura di una middleware è una soluzione migliore.

Un middleware campione può essere qualcosa di simile:

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 
  • È possibile effettuare il check IP utilizzando un elenco o una regex come detto @Jingo.
  • Se si utilizza l'autenticazione django e REMOTE_ADDR non è nell'elenco ALLOWED_IP_BLOCKS, quindi è possibile utilizzare is_authenticated per verificare se l'utente correlato si è connesso o meno.Ma per l'utilizzo di is_autheticated in un middleware personalizzato, il middleware personalizzato deve essere inserito dopoAuthenticationMiddleware, perché request.user è impostato su tale livello.

    MIDDLEWARE_CLASSES = (
        ... 
        'django.contrib.auth.middleware.AuthenticationMiddleware', 
        'path.to.my.NeedToLoginMiddleware', 
        ... 
    ) 
    
    • Se alcune viste non necessitano di questa autenticazione, allora si può fare un elenco di gli URL eccezionali e ottenere la richiesta URL da request.path e verificare se la richiesta URL richiede ip di controllo/autenticazione.

Maggiori informazioni su custom middleware classes

+1

Mettere il 'ALLOWED_IP_BLOCKS' nel * * settings.py, e accedervi con' settings.ALLOWED_IP_BLOCKS' (necessita 'da django.conf import Settings') consentirebbe una più bello configurazione, – luckydonald

1

IMO, la soluzione di questo con Django va bene se si tratta di un piccolo sito critica non le prestazioni.

È meglio tenere a bada gli utenti non autorizzati utilizzando il servizio Apache o Nginx. Per esempio, in Nginx ho queste righe nella mia configurazione del sito:

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

allowed_ips.conf è in/etc/nginx e guarda (qualcosa) come questo:

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

Credo che questo sia meglio perché i processi di Django relativamente lenti non vengono mai toccati dagli IP bloccati. Ciò è significativo se si stanno bloccando bot o altri intervalli di indirizzi nazionali per motivi di prestazioni o di sicurezza.

3

Puoi provare questo decoratore. Ho testato il suo bel lavoro:

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