【问题标题】:How to generate temporary URLs in Django如何在 Django 中生成临时 URL
【发布时间】:2009-09-01 00:58:07
【问题描述】:

想知道是否有生成在 X 天后过期的临时 URL 的好方法。希望通过电子邮件发送一个 URL,收件人可以单击该 URL 以访问网站的一部分,然后在一段时间后通过该 URL 无法访问该部分。不知道如何使用 Django、Python 或其他方式执行此操作。

【问题讨论】:

    标签: django url


    【解决方案1】:

    如果您不希望获得很大的响应率,那么您应该尝试将所有数据存储在 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 可能没有那么有用,根据您的数据,您可以尝试看看哪种方法最适合您。

    【讨论】:

    • 基本上每个 URL 都是供一个用户访问的,因此响应率不高。这个想法听起来很有趣,但我并没有 100% 理解它——一个小例子会很棒!
    【解决方案2】:

    型号

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

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

    【讨论】:

      【解决方案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。

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

        • 我想要做的是通过临时 URL 提供对表单的访问,因此目标访问者可以在 X 天内(链接过期之前)访问该 URL,它会调出表单。该表单将预先填充与生成的每个 URL 不同的数据。所以相同的形式,每个 URL 的数据不同。
        【解决方案5】:

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

        【讨论】:

        • 有趣。不确定我是否获得了阻止转发的方法,希望听到有关该方法的更多详细信息。
        • 我所说的转发是指某人向其他人发送链接。您设置了一次 cookie 并在您的应用中标记它设置,这样访问该 URL 的任何其他人都无法访问,因为他们没有 cookie。
        【解决方案6】:

        这可能有点矫枉过正,但您可以在模型上使用 uuid 字段并设置 Celerybeat 任务以在您选择的任何时间间隔更改 uuid。 如果 celery 太多并且可能是,您可以只存储 URL 首次发送的时间,然后在发送之后使用 timedelta 函数,如果经过的时间大于您想要的时间,则只需使用重定向。我认为第二种解决方案非常简单,并且很容易扩展。这将是一个模型的问题,该模型包含 URL、首次发送时间、最近发送时间、禁用标志和您认为该 URL 可以接受的 Delta。

        【讨论】:

          猜你喜欢
          • 2015-07-13
          • 2010-09-07
          • 2012-11-17
          • 2021-10-03
          • 2015-05-10
          • 1970-01-01
          • 2010-12-31
          • 2020-02-21
          • 1970-01-01
          相关资源
          最近更新 更多