【发布时间】:2009-09-01 00:58:07
【问题描述】:
想知道是否有生成在 X 天后过期的临时 URL 的好方法。希望通过电子邮件发送一个 URL,收件人可以单击该 URL 以访问网站的一部分,然后在一段时间后通过该 URL 无法访问该部分。不知道如何使用 Django、Python 或其他方式执行此操作。
【问题讨论】:
想知道是否有生成在 X 天后过期的临时 URL 的好方法。希望通过电子邮件发送一个 URL,收件人可以单击该 URL 以访问网站的一部分,然后在一段时间后通过该 URL 无法访问该部分。不知道如何使用 Django、Python 或其他方式执行此操作。
【问题讨论】:
如果您不希望获得很大的响应率,那么您应该尝试将所有数据存储在 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 值的 URL(正确引用 url)。在您的视图函数中,将这两个值与 decode_data 一起使用来检索原始数据。
zlib.compress 可能没有那么有用,根据您的数据,您可以尝试看看哪种方法最适合您。
【讨论】:
型号
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"),)
//当然你需要一些导入和模板
【讨论】:
您可以使用以下网址进行设置:
http://yoursite.com/temp/1a5h21j32
你的 URLconf 看起来像这样:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^temp/(?P<hash>\w+)/$', 'yoursite.views.tempurl'),
)
...其中 tempurl 是一个视图处理程序,它根据散列获取适当的页面。或者,如果页面过期,则发送 404。
【讨论】:
这取决于您想要做什么 - 诸如帐户激活或允许下载文件之类的一次性操作可以通过查找哈希、检查时间戳并执行操作或提供文件的视图来完成。
更复杂的东西,例如提供任意数据,还需要模型包含对该数据的一些引用,以便您可以决定发回什么。最后,允许访问多个页面可能需要在用户会话中设置一些内容,然后使用它来确定他们可以看到的内容,然后进行重定向。
如果您能提供更多关于您正在尝试做什么以及您对 Django 的了解程度的详细信息,我可以做出更具体的回复。
【讨论】:
我认为解决方案在于所有建议解决方案的组合。我建议使用过期会话,以便链接将在您在模型中指定的时间段内过期。结合重定向和中间件来检查会话属性是否存在并且请求的 url 需要它,您可以创建站点的一些安全部分,这些部分可以具有更好的 URL 来引用站点的永久部分。我用它来在有限的时间内展示设计/功能。这可以防止转发...我不这样做,但您可以在第一次单击后删除临时 url,因此只有会话属性将提供访问权限,从而更有效地限制一个用户。我个人不介意临时 url 是否被转发,因为知道它只会持续一段时间。修改后的表单也可以很好地跟踪受邀访问。
【讨论】:
这可能有点矫枉过正,但您可以在模型上使用 uuid 字段并设置 Celerybeat 任务以在您选择的任何时间间隔更改 uuid。 如果 celery 太多并且可能是,您可以只存储 URL 首次发送的时间,然后在发送之后使用 timedelta 函数,如果经过的时间大于您想要的时间,则只需使用重定向。我认为第二种解决方案非常简单,并且很容易扩展。这将是一个模型的问题,该模型包含 URL、首次发送时间、最近发送时间、禁用标志和您认为该 URL 可以接受的 Delta。
【讨论】: