Django加密网址中的主键

时间:2014-06-10 09:06:24

标签: python django primary-key django-urls

我环顾四周,但仍然不满意如何安全地加密我的django应用程序网址中的主要ID。

我的网址如下:

http://www.example.com/primary1_id/primary2_id/testing/

例如:

http://www.example.com/3/7/testing/

我想向用户显示以上网址:

http://www.example.com/623477897ghfjs23879/7829yfgweh/testing/ #encrypted key instead of primary id

在我的观点中,我应该能够从加密密钥中解码出primary1_id和primary2_id

我需要一些关于如何以最佳方式处理它的指导

提前致谢!

2 个答案:

答案 0 :(得分:2)

我编写了一个可以帮助您执行此操作的库:django-encrypted-id。这是一个示例模型:

from django.db import models

from encrypted_id.models import EncryptedIDModel


class Foo(EncryptedIDModel):
    text = models.TextField()

通过继承EncryptedIDModel,您可以将.ekey作为模型实例上的属性。这就是它们的样子:

In [1]: from tapp.models import Foo

In [2]: f = Foo.objects.create(text="asd")

In [3]: f.id
Out[3]: 1

In [4]: f.ekey
Out[4]: 'bxuZXwM4NdgGauVWR-ueUA..'

您可以进行反向查找:

In [5]: from encrypted_id import decode

In [6]: decode(f.ekey)
Out[6]: 1

如果你不能从helper基类继承,没问题,你可以使用encrypted_id包中的ekey()函数:

In [7]: from encrypted_id import ekey

In [8]: from django.contrib.auth.models import User

In [9]: ekey(User.objects.get(pk=1))
Out[9]: 'bxuZXwM4NdgGauVWR-ueUA..'

要进行反向查找,您可以使用两个帮助程序。第一个是由EncryptedIDManager提供的,如果你从EncryptedIDModel继承并且没有覆盖.objects,则默认使用它:

In [10]: Foo.objects.get_by_ekey(f.ekey)
Out[10]: <Foo: Foo object>

但有时你会更喜欢这种形式:

In [11]: Foo.objects.get_by_ekey_or_404(f.ekey)
Out[11]: <Foo: Foo object>

它的工作方式相同,但它不是提高DoesNotExist,而是提升Http404,因此可以在视图中使用它。

您的经理不是从EncryptedIDManager继承,您可以使用:

In [12]: e = ekey(User.objects.first())

In [13]: e
Out[13]: 'bxuZXwM4NdgGauVWR-ueUA..'

In [14]: get_object_or_404(User, e)
Out[14]: <User: amitu>

encrypted_id.get_object_or_404,以及EncryptedIDManager.get_by_ekey和EncryptedIDManager.get_by_ekey_or_404采取额外的关键字参数,可以根据需要进行过滤。

如果你是古玩,用于匹配生成的id的正则表达式是:

"[0-9a-zA-Z-_]+.{0,2}"

如果您使用smarturls,则可以使用以下网址格式:

"/<ekey:foo>/"

我建议在UUID上使用encrypted-id,as UUIDs have significant issues that should be considered(tldr:它们在磁盘和RAM上占用更多空间,并且索引比整数ID更低),如果你的目标只是使URL不可猜测的,加密的id是一种优越的方法。

如果您对使用的加密感到好奇:我正在使用来自pycrypto库的AES,并且在AES.CBC中使用SECRET_KEY作为密码(SECRET_KEY [:24])和IV(SECRET_KEY [-16:])模式。一般来说,建议不要使用静电IV,但CBC会抵消静电IV的一些问题。你问的静态IV有什么问题:如果纯文本“abc”和“abe”被加密,前两个字节将是相同的。现在这对我们来说并不是一个严重的问题,因为我正在加密的纯文本在有效载荷的开头使用CRC32,所以即使你有id,1,11,攻击者也不能说它们都以相同的第一个字符开头

该库还支持由于某种原因必须循环SECRET_KEY的场景,因此使用旧版SECRET_KEY加密的URL仍然可以在更改后解码(只要您在SECRET_KEYS设置中存储旧版本)。为了解密库,尝试每个密钥,并比较数据的CRC32以确定(确保事情进入这些事情),我们已正确解密。

请随时在encrypted-id github repo提出问题,如果您遇到任何问题,我很乐意提供帮助。该库支持python 2.7和3.5,以及django团队支持的所有django版本。

答案 1 :(得分:0)

$(function() { //on page load

    $( ".exampleclass" ).each(function( index ) { //replace each url
      var url = $(this).attr('href'); //get current url
      var encodedUrl = encodeURIComponent(url); //enconde url
      $(this).attr("href", encodedUrl); /replace
    });

});

结果:

http://10.91.161.54:8181/validate_/listActivi/314/

http://10.91.161.54:8181/validate_/%2Fvalidate_%2FlistActivi%2F314%2F%20