【问题标题】:How to send encrypted ids in admin URLs of django admin interface?如何在 django 管理界面的管理 URL 中发送加密的 id?
【发布时间】:2020-01-23 11:28:09
【问题描述】:

我有一个使用 django 管理界面的应用程序。此应用程序允许用户对其产品执行 CRUD 操作。在这些操作期间,管理 URL 会公开该产品的实际 ID 值,例如 https://localhost/product/1/change。我正在寻找一个选项来发送 URL 中显示的混淆 ID 值,例如https://localhost/product/F87BA2/change。有人可以分享您对如何实现这一目标的想法吗?

我已经有一个为给定 ID 提供混淆值的函数,但是如何在自动生成的管理 URL 中使用此函数?

谢谢!

【问题讨论】:

  • ID 总是一个数字吗?几位数?如果您只想混淆(而不是加密)它,只需选择另一个解码就可以完成这项工作,例如Base64 之类的。
  • @nostradamus,是的,ID 永远是一个自动递增的数字。基本上它是一个整数。是的,混淆就足够了,我有一个函数可以进行这种解码。但是如何使这个编码值成为管理 URL 的一部分是我的问题。由于这些管理 URL 是自动生成的,哪些文件需要更改/覆盖才能使用这些混淆值?
  • @Malathy 您可以随时重新定义管理员网址 - 但实际上,您为什么要为管理员执行此操作?它不应该是您网站的公共部分(我的意思是:它只应该由受信任的内部用户使用 - 如果您想向非员工登录用户公开某些版本功能,则不要使用管理员,您编写自己的表单和视图)
  • @brunodesthuilliers,管理界面供有限的客户根据他们与我们的订阅创建和/或自定义我们的应用程序。因此,我们为这些视图选择了 django 管理界面。在这种情况下,我们如何重新定义 admin url?请提出建议。
  • @Malathy 我建议您不要为此使用管理员,而是构建自己的视图和表单集。根据经验(长期经验),它实际上会为您节省很多时间:尝试使用管理员进行操作,您很快就会发现必须编写无论如何,您自己的视图和表单(和 url),然后您必须将它们插入管理中,然后覆盖这么多管理代码以使其满足您的需求,最终您将做更多的工作而不是您只需使用普通视图、表单和模板编写自己的专用应用程序即可。我的 2 美分...

标签: python django django-admin obfuscation


【解决方案1】:

可能你需要 slug 字段:https://docs.djangoproject.com/en/2.2/ref/models/fields/#slugfield 它完全符合您的要求。

【讨论】:

    【解决方案2】:

    大概可以使用UUIDField,可以作为唯一标识。您可以像这样将UUIDField 添加到模型中:

    import uuid
    
    class Product(models.Model):
        unique_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
    

    并将其与 url 一起使用,如下所示:

    # url
    
    path('product/<uuid:unique_id>', views.product, name='product')
    
    # view
    
    def product(request, unique_id):
         product = get_object_or_404(Product, unique_id=unique_id)
    

    另外,您可以使用UUIDField 作为主键,因为(来自文档):

    对于primary_key,通用唯一标识符是AutoField 的一个很好的替代方案。数据库不会为你生成UUID,建议使用default:

    【讨论】:

    • 如果我有一个 ID(自动增量)字段作为主键字段并添加一个 UUID 字段也是唯一的,我想了解在 django admin 中应该更改哪些内容以使管理员 URL 使用它UUID 字段而不是 URL 中显示的默认主键 ID?
    【解决方案3】:

    虽然我喜欢 Alexander Kononenko 的回答(我不知道 slugfield,感谢您指出这一点),但使用非常简单的方法可能仍然值得:

    import base64
    
    partnr='23'
    partobf=base64.b32encode((bytes(partnr, 'utf-8'))).decode('utf-8').replace('=', '')
    print(partobf)
    
    # reverse it, if you need to deduce a part number from a given URL
    partnrb=base64.b32decode('{}{}'.format(partobf, '='*(8-len(partobf)%8))).decode('utf-8')    
    print(partnrb)
    

    输出:

    GIZQ

    23

    这适用于任何字符串(不仅是数字),而且很容易反转。除了 Base32,您还可以使用 Base64 或任何其他使用与 URL 兼容的字符的编码。使用此方法,您可以将任何 ID 从明文转换为模糊文本,而无需字典,其中存储了两个值。

    但是,重要的是要指出,这些(以及到目前为止线程中出现的其他答案)都与加密无关任何。所以,可能,OP应该改变标题。

    【讨论】:

      猜你喜欢
      • 2015-09-08
      • 2011-01-07
      • 2023-03-07
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多