如何在Django中生成临时URL

时间:2009-09-01 00:58:08

标签: django url

想知道是否有一种很好的方法来生成在X天内过期的临时URL。想要通过电子邮件发送一个URL,收件人可以点击该URL以访问该网站的一部分,该网站在一段时间后通过该URL无法访问。不知道如何使用Django或Python,或其他方式。

6 个答案:

答案 0 :(得分:15)

如果您不希望获得较高的响应率,那么您应该尝试将所有数据存储在URL本身中。这样,您就不需要在数据库中存储任何内容,并且数据存储与响应成比例,而不是发送的电子邮件。

更新:假设您有两个对每个用户都唯一的字符串。您可以打包它们并使用这样的保护哈希解压缩它们:

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)

这会产生:

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

在您的电子邮件中,添加一个既包含哈希值又包含enc值的网址(正确的网址引用)。在视图函数中,将这两个值与decode_data一起使用以检索原始数据。

zlib.compress可能没那么有用,根据您的数据,您可以尝试查看哪种方式最适合您。

答案 1 :(得分:5)

模型

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

视图

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))

网址

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

//当然你需要一些导入和模板

答案 2 :(得分:3)

您可以使用以下网址进行设置:

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

你的URLconf看起来像这样:

from django.conf.urls.defaults import *

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

...其中tempurl是一个视图处理程序,它根据哈希获取适当的页面。或者,如果页面已过期,则发送404。

答案 3 :(得分:1)

这取决于你想做什么 - 可以通过查看哈希,检查时间戳并执行操作或提供文件的视图来完成诸如帐户激活或允许下载文件之类的一次性操作。

更复杂的东西,例如提供任意数据,也需要包含对该数据的一些引用的模型,以便您可以决定要发回的内容。最后,允许访问多个页面可能涉及在用户会话中设置某些内容,然后使用它来确定他们可以看到的内容,然后重定向。

如果您可以提供有关您正在尝试做什么的更多细节以及您对Django的了解程度,我可以做出更具体的回复。

答案 4 :(得分:1)

我认为解决方案在于所有建议解决方案的组合。我建议使用到期会话,以便链接在您在模型中指定的时间段内到期。结合重定向和中间件来检查会话属性是否存在以及请求的网址是否需要它,您可以创建网站的某些安全部分,这些部分可以具有引用网站永久部分的更好的URL。我使用它来在有限的时间内演示设计/功能。这可以防止转发...我不这样做但你可以在第一次点击后删除临时网址,这样只有会话属性才能提供访问权限,从而更有效地限制一个用户。我个人不介意,如果临时网址被转发,知道它只会持续一段时间。以修改后的形式运行良好,以跟踪受邀访问。

答案 5 :(得分:0)

这可能有些过分,但是您可以在模型上使用uuidfield并设置Celerybeat任务以在您选择的任何时间间隔更改uuid。 如果celery太多(可能是太多),则可以只存储第一次发送URL的时间,此后每次发送时都使用timedelta函数,并且如果经过的时间大于您想要的时间,则仅使用重定向。我认为第二种解决方案非常简单,可以轻松扩展。这将是一个具有URL的模型,第一次发送的时间,最近发送的时间,一个禁用的标志以及一个您认为URL可以接受的Delta的问题。