【发布时间】:2020-04-15 09:10:29
【问题描述】:
我目前有一个自定义用户模型,其中一些字段应该被加密(数据端),但在 Django Admin 上,它们需要被解密以显示实际数据,所以我有 encrypt_string() 和 decrypt_string() 函数处理它。
我的用户模型:
class User(AbstractUser):
uid = models.CharField(
"uid", max_length=255, null=True, blank=True)
nickname = models.CharField(
"Nickname", max_length=255, null=True, blank=True)
eth_address = models.CharField(
"Eth address", max_length=255, null=True, blank=True)
eth_private_key = models.CharField(
"Eth private key", max_length=255, null=True, blank=True)
evt_address = models.CharField(
"Evt address", max_length=255, null=True, blank=True)
evt_private_key = models.CharField(
"Evt private key", max_length=255, null=True, blank=True)
eth_address、eth_private_key、evt_address 和 evt_private_key 在进行任何类型的保存或编辑时都需要加密
目前,当我的服务器从 api 请求时,它将创建一个默认用户(处理 django-rest-framework 的自定义 authentication_class):
existed_user_check = User.objects.filter(uid=uid).exists()
if not existed_user_check:
random_password = ''.join(["{}".format(randint(0, 9)) for num in range(0, 6)])
eth_address, eth_private_key = generate_eth()
evt_address, evt_private_key = generate_evt()
new_user = User(
username=uid,
uid=uid,
eth_address=encrypt_string(eth_address),
eth_private_key=encrypt_string(eth_private_key),
evt_address=encrypt_string(evt_address),
evt_private_key=encrypt_string(evt_private_key)
)
new_user.set_password(random_password)
new_user.save()
在我的 Django Admin 上,我在 admin.py 中编写了以下内容来处理解密(在更改视图上显示数据时)和加密(在对这 4 个字段进行任何保存或编辑时):
user_profile_encrypt_fields = [
'eth_address',
'eth_private_key',
'evt_address',
'evt_private_key'
]
class UserAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserAdminForm, self).__init__(*args, **kwargs)
for field in user_profile_encrypt_fields:
if getattr(self.instance, field) is not None:
try:
self.initial[field] = decrypt_string(getattr(self.instance, field))
except Exception as e:
pass
class UserAdminCustom(admin.ModelAdmin):
# UserAdminForm handle decrypt data
form = UserAdminForm
exclude = ('password', 'last_login', 'is_superuser', 'is_staff', 'groups',
'user_permissions', 'username', 'first_name', 'last_name', 'is_active', 'date_joined')
def get_queryset(self, request):
qs = super(UserAdminCustom, self).get_queryset(request)
return qs.filter(is_staff=False)
def get_readonly_fields(self, request, obj=None):
return ('id', 'created', 'modified')
# save_model() handle encrypt data on saving
def save_model(self, request, obj, form, change):
for field in form.changed_data:
if form.cleaned_data.get(field) is not None:
if field in user_profile_encrypt_fields:
encrypted_value = encrypt_string(form.cleaned_data.get(field))
setattr(obj, field, encrypted_value)
obj.save()
admin.site.register(User, UserAdminCustom)
自定义 UserAdminForm 让我解密数据,以便管理员在进行编辑或检查时可以看到它是什么。 解密后的数据能够正确显示在更改视图上
save_model() 将在管理员编辑 Django Admin 更改视图上的字段时处理数据加密。
我目前的问题:
注意事项:
这些字段中的数据是存在的,所以我只谈论 django admin 上的编辑对象部分。
当我尝试编辑任何字段并保存它(应该加密)时,该字段被加密并保存,但它下面的字段(它的实际加密数据)现在更改为它的实际数据(未加密)
我在更改视图上编辑 evt_address 并保存后
使用form = UserAdminForm时的解密数据
在 UserAdminCustom 上注释掉 # form = UserAdminForm 以便显示实际数据
我打印了getattr(self.instance, field)在加载django admin change view时查看加密数据,得到以下4个加密字段:
web_1 | eth_address : gAAAAABeAcoI08bH2fQqJboZFxg6xn5RCxdRopllS6fDeyRmsC3qzsTXo88NVYOb58eeX5IXQpxqcGhbLr8wRRoWSKQsX5vLbPPhmWqUiqf0XYQvdWUhhgYxxMwwqgEOwU2OtJfkZ0p6
web_1 | eth_private_key : gAAAAABeAcoIp1V9sKNnL-dO-fWH1W1oM7hbqky44aRLchmTtvckaaZdaKuXo1xIIozx3xl40Y2Ct3YAyCOfkJJranKgTNDcVhndYdu5-awOuYpPCJKkSSia7IP_gWjLE91Gh8vsGnkn1iEkrLaho2ff0vVHS1QgGaJxji5m7cwCk0tqSp2AIeA=
web_1 | evt_address : gAAAAABeAcoIM3rywSgAPL611WUoWLJ9mqIgUHhZn8KDQd9hi9xHzgRri0EkoS_yBvwQyzdH72RWJRsDCs38oF9P8HHW_wFDWQ==
web_1 | evt_private_key : 1814067
所以我的evt_private_key 数据在我编辑evt_address 值并保存后更改为1814067
为什么会这样,我很困惑是什么原因造成的。
希望有人可以帮助我
【问题讨论】:
标签: python django encryption django-admin