【问题标题】:url design: ways to hide pk/id from urlurl 设计:从 url 隐藏 pk/id 的方法
【发布时间】:2012-04-11 10:16:03
【问题描述】:

要访问我网站上某个项目的详细信息页面,可以使用以下网址

<mydomain>/item/1

1 是 Item 的主键

我正在寻找一种解决方案,让我可以根据以下要求重新设计 url:

  • 从 url 中排除 pk 或任何顺序 ID
  • 能够唯一访问项目详细信息页面

我打算将这个问题作为一个一般性的网页设计问题来问,但只是想我应该提到我正在使用 Python/Django。

【问题讨论】:

    标签: python django url


    【解决方案1】:

    我不喜欢 slugfield 选项,因为它向数据库添加了额外的查询。

    我在一个项目中做了以下事情:

    我的网址如下所示:

    <domain>/item/5927/728e26e9464a171b228bc9884ba3e4f76e2f8866/
    

    这是:

    <domain>/item/<id>/<hash>/
    

    如果您不知道哈希值,您将无法访问该项目:

    urls.py:

    url(r'^item/(?P<id>\d+)/(?P<hash>\w+)/$', 'rwapp.views.item', name='item')
    

    views.py:

    from hashlib import sha1
    
    def item(request,id=None,hash=None):
        if not id:
            return HttpResponseRedirect("/home")
        if hash:
            chash = sha1("secret_word%s"%id).hexdigest()
            if not chash==hash:
                return HttpResponseRedirect("/home")
        else:
            return HttpResponseRedirect("/home")
    

    当然,每次渲染 URL 时都必须添加 // 部分。

    【讨论】:

      【解决方案2】:

      你需要在 URL 中有 一些 种标识符,并且这个标识符:

      1. 必须是唯一的(两个对象不能有相同的 id)
      2. 必须是永久的(对象的 id 永远不能改变)

      所以没有那么多选项,对象的主键是最好的选择。如果由于某种原因您不能使用它(为什么不呢?),您可以对其进行编码或混淆:请参阅this question 及其答案,了解有关如何执行此操作的一些想法。

      Stack Overflow 自己的 URL 设计值得一看。您可以通过表单的任何 URL 找到此问题

      https://stackoverflow.com/questions/9897050/any-text-you-like-here!

      这允许 URL 包含来自问题标题的关键字(用于搜索引擎),同时还能够在标题更改时更改而不破坏旧链接。

      【讨论】:

      • 谢谢加雷斯。您的回答为我模糊的想法提供了很好的指导。我不想在 url 中使用自动生成的 pk 的原因是因为我不希望外人能够弄清楚网站上创建了多少项目。这是给您的后续问题。是坚持自动生成的pk并采用encode/obfuscate解决方案,还是设计和使用一个函数来生成非连续的pk更好?谢谢。
      • 坚持使用数据库中自动生成的主键并在 URL 中使用编码。 (如果您在 URL 中进行编码,如果您发现它有问题,您始终可以选择更改您的编码方案,但如果您在数据库中进行,则很难更改。)
      【解决方案3】:

      这样做的一种肮脏方式是使用 cookie 来保存被请求对象的 id。我不是特别喜欢这个想法,除非你有编写/扩展框架的经验,否则很难获得一个框架来支持。

      一些框架支持使用 id= 属性而不是 URL 路径。如果将其作为 POST 参数包含在内,它将不可见,但将页面与 POST 链接在一起将具有挑战性,因为它旨在提交表单数据。

      我建议的方法是,如果这是一个真正的要求,则使用除 ids 之外的其他东西来唯一标识您的对象。然后将其包含在您的 URL 中。虽然从数据库的角度来看这不是一个理想的设计,但它确实有好处。首先,您必须考虑为什么要隐藏此信息。如果是出于 SEO 目的,则在 URL 中使用项目名称而不是其 id 是您想要的。真正的问题是,如果您只是将此信息隐藏在其他一些数据通道中,那么您对于不同的资源就有相同的 URL。由于许多原因,这低于标准,其中最重要的是 SEO 和用户书签。使用人类可读的密钥可以解决两种情况和其他情况,同时激怒您的 DBA。使用这种方法也应该很容易直接或通过在控制器中使用额外的代码来进行转换,这可能会让您与 DBA 建立正确的关系。

      【讨论】:

        【解决方案4】:

        对于 Django,你可以给你的模型一个SlugField,然后让视图使用它来查找模型。

        MyModel.objects.filter(slug_field_name='some-slug-value')
        

        确保上面有某种形式的唯一性约束。

        【讨论】:

          【解决方案5】:

          嗯,有很多方法可以做到这一点。由于您使用的是 django,请查看SlugField。或者您生成 UUID 并将其存储在每个项目上以供访问。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-04-12
            • 2019-01-11
            • 2012-08-15
            • 1970-01-01
            • 2018-07-08
            • 1970-01-01
            • 2019-07-10
            相关资源
            最近更新 更多