我正在处理的项目使用Fernet进行加密,我们需要存储访问令牌。出于某种原因,在shell中运行代码时解密工作正常,但测试失败,因为访问令牌没有被解密。
第一个问题
在Django shell中运行代码和通过测试运行代码之间有区别吗?这可以解释我的麻烦。
第二个问题
如果在Django shell中运行代码与测试期间没有区别,则问题来自其他地方。请继续阅读并查看下面的代码,以便更清楚。
在shell和测试中我都从数据库加载相同的对象,让我们调用这个对象facebookToken。当我运行facebookToken.decryptedAccessToken时,它工作得很好。但是,运行测试时相同的代码不起作用,decryptedAccessToken返回加密值!
处理加密的类
class Gatekeeper(object):
"""A simple class to encrypt en decrypt strings."""
key = settings.FERNET_KEY
def encrypt(self, secret):
"""Return an encrypted string.
attribute secret: a string to encrypt
"""
fernet = Fernet(self.key)
# cast string to bytes
secret = secret.encode()
encryptedSecret = fernet.encrypt(secret)
return encryptedSecret
def decrypt(self, secret):
"""Return a decrypted string.
attribute secret: a secret string to decrypt
"""
print '\n \n secret', secret
fernet = Fernet(self.key)
# cast string to bytes
secret = secret.encode()
print '\n \n ENCODED secret', secret
decryptedSecret = fernet.decrypt(secret)
print '\n \n decryptedSecret', decryptedSecret
return decryptedSecret
自定义加密文本字段类。
class EncryptedTextField(models.TextField):
"""A custom textfield for storing sensitive information."""
description = "A textfield for storing sensitive information."
def __init__(self, *args, **kwargs):
super(EncryptedTextField, self).__init__(*args, **kwargs)
def get_db_prep_value(self, value, connection, prepared=False):
"""Return encrypted value or None.
This method encryps the value before storing it in the database.
"""
if value is not None:
value = Gatekeeper().encrypt(value)
return value
抽象AccessToken类
class AccessToken(models.Model):
"""Abstract class for Access tokens.
Depends on Gatekeerp, EncryptedTextField, and User class in core app!
"""
owner = models.ForeignKey('core.User')
socialMediaChannel = models.IntegerField(
choices=socialMediaChannelList, null=False, blank=False
)
accessToken = EncryptedTextField(null=False, blank=False)
accessTokenSecret = EncryptedTextField(null=True, blank=True)
lastUpdate = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
@classmethod
def getAccessTokens(cls, user, socialMediaChannel):
"""Return a list with AccessToken objects. Filter on user and
socialMediaChannel.
attribute user: a user object
attribute socialMediaChannel: a socialMediaChannel
"""
accessTokens = cls.objects.filter(
owner=user,
socialMediaChannel=socialMediaChannel
)
return accessTokens
@property
def decryptedAccessToken(self):
"""Return decrypted accessToken."""
return Gatekeeper().decrypt(self.accessToken)
@property
def decryptedAccessTokenSecret(self):
"""Return decrypted accessTokenSecret."""
return Gatekeeper().decrypt(self.accessTokenSecret)