2012-09-12 19 views
8

Tengo una pequeña aplicación Django con una vista que quiero restringir a ciertos usuarios. Cualquier persona de una red específica debería poder ver esa vista sin ninguna autenticación adicional, basada solo en la dirección IP. A cualquier persona que no pertenezca a este rango de IP se le debe pedir una contraseña y debe autenticarse contra la administración de usuarios predeterminada de Django.Autenticar por dirección IP en Django

Supongo que tengo que escribir un servidor de autenticación personalizado para eso, pero la documentación me confunde ya que la función authenticate() parece esperar una combinación de nombre de usuario/contraseña o un token. No tengo claro cómo autenticar usando direcciones IP aquí.

¿Cuál sería la forma correcta de implementar la autenticación basada en direcciones IP en Django? Preferiría usar la mayor cantidad posible de funciones de biblioteca existentes para el código relacionado con la seguridad en lugar de escribir todo yo mismo.

Respuesta

3

No es necesario escribir un back-end de autenticación para el caso de uso que haya escrito. Escribir un despachador basado en IP en la capa de middleware probablemente sea suficiente

Si la (s) url (es) de su aplicación coinciden, process_request debe buscar un usuario django autenticado y unir ese usuario a una lista blanca.

6

También puede escribir un pequeño decorador para este propósito:

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 es en mi caso un archivo (allowedIps.py) que almacena las expresiones regulares para las direcciones IP permitidas en una tupla de esta manera:

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

Espero que esto pueda ayudar o dar una idea. Nota: si devuelve authenticated_by_ip a la vista decorada, su vista tendrá que aceptar ese parámetro, también puede omitirlo, si no lo necesita. También puede definir las expresiones regulares de forma más precisa para aceptar solo dígitos de hasta tres.

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 

Es necesario allow_ip en que el modelo PerfilUsuario, que ahorrar en el registro o cambios en la página de edición del usuario

9

Hay dos enfoques adecuados para ese tipo de autenticación:

  • Como decorador: si algunas de las vistas (pero no muchas de ellas) requieren esta verificación, entonces es mejor escribir un decorador para eso (algo como @Jingo había escrito)
  • Como Middleware: si es necesario hacer esa comprobación por todas (o muchas) vistas, en lugar de utilizar un decorador, escribir una middleware es una mejor solución.

Una muestra de middleware puede ser algo como:

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 
  • Puede hacer el cheque IP utilizando una lista o una expresión regular como se ha mencionado @Jingo.
  • Si está utilizando la autenticación django y REMOTE_ADDR no está en la lista ALLOWED_IP_BLOCKS, puede usar is_authenticated para verificar si el usuario relacionado ha ingresado o no.Pero para usar is_autheticated en un middleware personalizado, su middleware personalizado debe colocarse después deAuthenticationMiddleware, porque request.user está establecido en ese nivel.

    MIDDLEWARE_CLASSES = (
        ... 
        'django.contrib.auth.middleware.AuthenticationMiddleware', 
        'path.to.my.NeedToLoginMiddleware', 
        ... 
    ) 
    
    • Si un par de puntos de vista no requieren esta autenticación, entonces se puede hacer una lista de direcciones URL excepcionales y obtener la solicitud de URL de request.path y comprobar si la petición de URL requiere registro/autenticación IP.

Más información sobre custom middleware classes

+1

Poner el 'ALLOWED_IP_BLOCKS' en el settings.py * *, y para acceder a él con' settings.ALLOWED_IP_BLOCKS' (necesita 'Settings' de importación django.conf) permitiría una mejor configuración, – luckydonald

1

OMI, la solución de este con Django es bien si es un no el rendimiento del sitio crítico pequeña.

Es mejor mantener a raya a los usuarios no autorizados utilizando su servicio Apache o Nginx. Por ejemplo, en Nginx tengo estas líneas en la configuración de mi sitio:

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

allowed_ips.conf se encuentra en/etc/nginx y mira (algo) así:

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

Creo que esto es mejor porque los procesos relativamente lentos de Django nunca son tocados por las direcciones IP bloqueadas. Esto es importante si bloquea bots u otros rangos de direcciones de país por razones de rendimiento o seguridad.

3

Puede probar este decorador. He probado su funcionamiento muy bien:

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