我正在web.py中构建一个应用程序,但在MySQL中存储加密数据时遇到了一些麻烦。
PyCrypto创建的密码文本如下:“\x06\x7f\x81\xa0\xf4d\x00H\xef\xd0\x18[c\x18Z\xf8
”,打印时显示为“ôdHïÐ[cZø
”
但是,MySQL将其存储为:???d H??[cZ?
我以下列方式存储它:
query_string = "INSERT INTO %s (%s) VALUES (\"%s\")" % (table, column, value)
我在连接数据库后尝试使用“SET character_set_connection=utf8
”,但结果没有产生任何变化。
我显然缺少一些非常重要的东西。有什么想法吗?
答案 0 :(得分:3)
MySQL正在尝试将您的字节字符串存储在字符列中。因为连接字符集是UTF-8但字节字符串不代表有效的UTF-8序列,所以它会受到损坏。
要正确地将原始字节输入数据库,您需要:
使列成为BINARY类型(或通常是带二进制排序规则的字符类型),
使用参数化查询将数据导入数据库,而不是将它们插入到查询字符串中,在那里它们可能与非二进制(Unicode)内容混合。
你应该使用参数化查询,因为你现在使用的字符串插值没有转义,容易受到SQL注入的攻击。在web.py中可能看起来像:
query_string= 'INSERT INTO %s (%s) VALUES ($value)' % (table, column)
db.query(query_string, vars= {'value': value})
(假设table
和column
值已知良好。)
这样做也意味着您不必担心美元符号。
另一种方法是使用普通字符串,编码非ASCII字节。你在当前的解决方法中使用uucode进行此操作,但是base64将是一种更常见的替代方法,在Python中更容易实现(ciphertext.encode('base64')
)。十六进制编码(.encode('hex')
)在散列的情况下最常见。
答案 1 :(得分:0)
我找到了解决方案。我不确定它有多优雅,但它是我能想到的最好的。
ENCODING:
1)import binascii
2)ciphertext = cipher.encrypt(plaintext)
3)asciitext = binascii.b2a_uu(ciphertext)
4)webpy_workaround = asciitext.replace('$', 'DOLLARSIGN') //if there are dollar signs in the text, webpy will try to use anything afterward, and will complain at you.
5)将webpy_workaround存储到sql。
解码:
1)从SQL中检索值
2)asciitext = sql_value.replace('DOLLARSIGN', '$')
3)ciphertext = binascii.a2b_uu(asciitext)
4)plaintext = cipher.decrypt(ciphertext)