如何在Django中生成临时URL

时间:2021-10-01 15:57:23

Wondering if there is a good way to generate temporary URLs that expire in X days. Would like to email out a URL that the recipient can click to access a part of the site that then is inaccessible via that URL after some time period. No idea how to do this, with Django, or Python, or otherwise.

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

5 个解决方案

#1


15  

If you don't expect to get a large response rate, then you should try to store all of the data in the URL itself. This way, you don't need to store anything in the database, and will have data storage proportional to the responses rather than the emails sent.

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

Updated: Let's say you had two strings that were unique for each user. You can pack them and unpack them with a protecting hash like this:

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

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)

This produces:

这会产生:

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

In your email, include a URL that has both the hash and enc values (properly url-quoted). In your view function, use those two values with decode_data to retrieve the original data.

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

The zlib.compress may not be that helpful, depending on your data, you can experiment to see what works best for you.

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

#2


5  

models

楷模

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

views

意见

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

//of course you need some imports and templates

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

#3


3  

You could set this up with URLs like:

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

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

Your URLconf would look something like this:

你的URLconf看起来像这样:

from django.conf.urls.defaults import *

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

...where tempurl is a view handler that fetches the appropriate page based on the hash. Or, sends a 404 if the page is expired.

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

#4


1  

It depends on what you want to do - one-shot things like account activation or allowing a file to be downloaded could be done with a view which looks up a hash, checks a timestamp and performs an action or provides a file.

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

More complex stuff such as providing arbitrary data would also require the model containing some reference to that data so that you can decide what to send back. Finally, allowing access to multiple pages would probably involve setting something in the user's session and then using that to determine what they can see, followed by a redirect.

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

If you could provide more detail about what you're trying to do and how well you know Django, I can make a more specific reply.

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

#5


1  

I think the solution lies within a combination of all the suggested solutions. I'd suggest using an expiring session so the link will expire within the time period you specify in the model. Combined with a redirect and middleware to check if a session attribute exists and the requested url requires it you can create somewhat secure parts of your site that can have nicer URLs that reference permanent parts of the site. I use this for demonstrating design/features for a limited time. This works to prevent forwarding... I don't do it but you could remove the temp url after first click so only the session attribute will provide access thus more effectively limiting to one user. I personally don't mind if the temp url gets forwarded knowing it will only last for a certain amount of time. Works well in a modified form for tracking invited visits as well.

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

#1


15  

If you don't expect to get a large response rate, then you should try to store all of the data in the URL itself. This way, you don't need to store anything in the database, and will have data storage proportional to the responses rather than the emails sent.

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

Updated: Let's say you had two strings that were unique for each user. You can pack them and unpack them with a protecting hash like this:

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

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)

This produces:

这会产生:

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

In your email, include a URL that has both the hash and enc values (properly url-quoted). In your view function, use those two values with decode_data to retrieve the original data.

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

The zlib.compress may not be that helpful, depending on your data, you can experiment to see what works best for you.

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

#2


5  

models

楷模

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

views

意见

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

//of course you need some imports and templates

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

#3


3  

You could set this up with URLs like:

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

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

Your URLconf would look something like this:

你的URLconf看起来像这样:

from django.conf.urls.defaults import *

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

...where tempurl is a view handler that fetches the appropriate page based on the hash. Or, sends a 404 if the page is expired.

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

#4


1  

It depends on what you want to do - one-shot things like account activation or allowing a file to be downloaded could be done with a view which looks up a hash, checks a timestamp and performs an action or provides a file.

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

More complex stuff such as providing arbitrary data would also require the model containing some reference to that data so that you can decide what to send back. Finally, allowing access to multiple pages would probably involve setting something in the user's session and then using that to determine what they can see, followed by a redirect.

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

If you could provide more detail about what you're trying to do and how well you know Django, I can make a more specific reply.

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

#5


1  

I think the solution lies within a combination of all the suggested solutions. I'd suggest using an expiring session so the link will expire within the time period you specify in the model. Combined with a redirect and middleware to check if a session attribute exists and the requested url requires it you can create somewhat secure parts of your site that can have nicer URLs that reference permanent parts of the site. I use this for demonstrating design/features for a limited time. This works to prevent forwarding... I don't do it but you could remove the temp url after first click so only the session attribute will provide access thus more effectively limiting to one user. I personally don't mind if the temp url gets forwarded knowing it will only last for a certain amount of time. Works well in a modified form for tracking invited visits as well.

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