2009-09-01 17 views
14

Preguntarse si existe una buena forma de generar URL temporales que caducan en X días. Quisiera enviar por correo electrónico una URL en la que el destinatario puede hacer clic para acceder a una parte del sitio que luego es inaccesible a través de esa URL después de un período de tiempo. No tengo idea de cómo hacer esto, con Django o Python, o de lo contrario.Cómo generar URL temporales en Django

Respuesta

15

Si no espera obtener una gran tasa de respuesta, entonces debería tratar de almacenar todos los datos en la URL misma. De esta forma, no necesita almacenar nada en la base de datos, y tendrá un almacenamiento de datos proporcional a las respuestas en lugar de los correos electrónicos enviados.

Actualizado: digamos que tiene dos cadenas que son únicas para cada usuario. Puede empacar y desempacar con un hash proteger de esta manera:

import hashlib, zlib 
import cPickle as pickle 
import urllib 

my_secret = "michnorts" 

def encode_data(data): 
    """Turn `data` into a hash and an encoded string, suitable for use with `decode_data`.""" 
    text = zlib.compress(pickle.dumps(data, 0)).encode('base64').replace('\n', '') 
    m = hashlib.md5(my_secret + text).hexdigest()[:12] 
    return m, text 

def decode_data(hash, enc): 
    """The inverse of `encode_data`.""" 
    text = urllib.unquote(enc) 
    m = hashlib.md5(my_secret + text).hexdigest()[:12] 
    if m != hash: 
     raise Exception("Bad hash!") 
    data = pickle.loads(zlib.decompress(text.decode('base64'))) 
    return data 

hash, enc = encode_data(['Hello', 'Goodbye']) 
print hash, enc 
print decode_data(hash, enc) 

Esto produce:

849e77ae1b3c eJzTyCkw5ApW90jNyclX5yow4koMVnfPz09JqkwFco25EvUAqXwJnA== 
['Hello', 'Goodbye'] 

En su correo electrónico, incluir una dirección URL que tiene tanto la ENC valores hash y (URL- adecuadamente citado). En su función de vista, use esos dos valores con decode_data para recuperar los datos originales.

zlib.compress puede no ser tan útil, dependiendo de sus datos, puede experimentar para ver qué funciona mejor para usted.

+0

Básicamente, cada URL sería para que un usuario tenga acceso, por lo que no es una gran tasa de respuesta. Esta idea suena interesante, pero no la estoy logrando al 100%, ¡un pequeño ejemplo sería genial! – chacmool

3

Se puede configurar esto con URLs como:

http://yoursite.com/temp/1a5h21j32 

Tu URLconf podría ser algo como esto:

from django.conf.urls.defaults import * 

urlpatterns = patterns('', 
    (r'^temp/(?P<hash>\w+)/$', 'yoursite.views.tempurl'), 
) 

... donde tempurl es un manejador de vista que recupera la página apropiada basada en el hash. O envía un 404 si la página ha caducado.

1

Depende de lo que desee hacer: las acciones one-shot como la activación de cuenta o permitir que un archivo se descargue se pueden hacer con una vista que busca un hash, verifica una marca de tiempo y realiza una acción o proporciona un archivo .

Las cosas más complejas, como proporcionar datos arbitrarios, también requerirían que el modelo contenga alguna referencia a esos datos para que pueda decidir qué devolver. Finalmente, permitir el acceso a múltiples páginas probablemente implicaría establecer algo en la sesión del usuario y luego usarlo para determinar lo que pueden ver, seguido de un redireccionamiento.

Si pudiera proporcionar más detalles sobre lo que está tratando de hacer y qué tan bien conoce a Django, puedo darle una respuesta más específica.

+0

Lo que quiero hacer es proporcionar acceso a un formulario a través de la URL temporal, para que el visitante objetivo pueda ir a la URL dentro de X días (antes de que el enlace caduque) y abrir el formulario. El formulario se rellenaría con datos que diferirían con cada URL generada. Así que la misma forma, diferentes datos por URL. – chacmool

5

modelos

class TempUrl(models.Model): 
    url_hash = models.CharField("Url", blank=False, max_length=32, unique=True) 
    expires = models.DateTimeField("Expires") 

vistas

def generate_url(request): 
    # do actions that result creating the object and mailing it 

def load_url(request, hash): 
    url = get_object_or_404(TempUrl, url_hash=hash, expires__gte=datetime.now()) 
    data = get_some_data_or_whatever() 
    return render_to_response('some_template.html', {'data':data}, 
           context_instance=RequestContext(request)) 

URLs

urlpatterns = patterns('', url(r'^temp/(?P<hash>\w+)/$', 'your.views.load_url', name="url"),) 

// por supuesto que necesitan algunas importaciones y plantillas

1

Creo que la solución se encuentra dentro de una combinación de todas las soluciones sugeridas. Sugeriría usar una sesión vencida para que el enlace caduque dentro del período de tiempo que especifique en el modelo.Combinado con un redireccionamiento y un middleware para verificar si existe un atributo de sesión y lo requiere la URL solicitada, puede crear partes algo seguras de su sitio que puedan tener URL más bonitas que hagan referencia a partes permanentes del sitio. Lo uso para demostrar el diseño/características por tiempo limitado. Esto funciona para evitar el reenvío ... No lo hago, pero podría eliminar la url temporal después del primer clic, de modo que solo el atributo de sesión proporcionará acceso, lo que limitará de manera más efectiva a un usuario. Personalmente, no me importa si la URL temporal se reenvía sabiendo que solo durará una cierta cantidad de tiempo. Funciona bien en una forma modificada para el seguimiento de visitas invitadas también.

+0

Interesante. No estoy seguro de obtener el método para evitar el reenvío, me encantaría escuchar más detalles sobre ese enfoque. – chacmool

+0

lo que quiero decir con reenvío es que alguien envíe un enlace a otra persona. Establece la cookie una vez y la marca en su aplicación de modo que cualquier otra persona que acceda a la URL no tenga acceso porque no tiene la cookie. – mogga