更新(解决方案)
由于这篇文章似乎得到了相当多的关注,我想让您知道解决方案最终是enctype
在声明中提供适当的(内容类型)参数<FORM>
。您必须将该值设置为multipart/form-data
以防止使用默认编码类型进行编码application/x-www-form-urlencoded
。下面是 w3.org上 HTML 文档中的表单的一小段摘录:
内容类型“application/x-www-form-urlencoded”对于发送大量二进制数据或包含非 ASCII 字符的文本效率低下。内容类型“multipart/form-data”应用于提交包含文件、非 ASCII 数据和二进制数据的表单。
这是正确的 FORM 声明:
<FORM method="POST" action="/path/to/file/" name="encryptedForm" enctype="multipart/form-data">
最初的问题
我正在研究一个表单垃圾邮件保护类,它基本上使用 mcrypt 将表单字段名称替换为加密值。这样做的问题是 mcrypt 加密不仅限于会使表单字段无效的字母数字字符。 鉴于下面的代码,您能想到为什么我在解密已经加密的数组的值时遇到问题的任何原因吗?
/**
* Two way encryption function to encrypt/decrypt keys with
* the DES encryption algorithm.
*/
public static function encryption($text, $encrypt = true)
{
$encrypted_data = '';
$td = mcrypt_module_open('des', '', 'ecb', '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
if (mcrypt_generic_init($td, substr(self::$randomizer, 16, 8), $iv) != -1) {
if ($encrypt) {
// attempt to sanitize encryption for use as a form element name
$encrypted_data = mcrypt_generic($td, $text);
$encrypted_data = base64_encode($encrypted_data);
$encrypted_data = 'i' . strtr($encrypted_data, '+/=', '-_.');
self::$encrypted[] = $encrypted_data;
} else {
// reverse form element name sanitization and decrypt
$text = substr($text, 1);
$text = strtr($text, '-_.', '+/=');
$text = base64_decode($text);
$encrypted_data = mdecrypt_generic($td, $text);
}
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
return $encrypted_data;
}
我稍后使用以下方法调用设置隐藏表单元素的值:
base64_encode(serialize(self::$encrypted))
本质上,隐藏字段包含所有表单字段的数组,这些字段使用其加密值进行加密。这样我就知道哪些字段需要在后端解密。提交表单后,该字段将在后端使用以下代码进行解析:
// load the mapping entry
$encrypted_fields = $input->post('encrypted', '');
if (empty($encrypted_fields)) {
throw new AppException('The encrypted form field was empty.');
}
// decompress array of encrypted fields
$encrypted_fields = @unserialize(base64_decode($encrypted_fields));
if ($encrypted_fields === false) {
throw new AppException('The encrypted form field was not valid.');
}
// get the mapping of encrypted keys to key
$data = array();
foreach ($_POST as $key => $val) {
// if the key is encrypted, add to data array decrypted
if (in_array($key, $encrypted_fields)) {
$decrypted = self::encryption($key, false);
$data[$decrypted] = $val;
unset($_POST[$key]);
} else {
$data[$key] = $val;
}
}
// merge $_POST array with decrypted key array
$_POST += $data;
我尝试解密加密的表单字段密钥失败了。它只是在$_POST
数组中创建一个新的乱码键。我的猜测是,要么base64_encoding
或serialization
正在从$encrypted_data
. 有人可以验证这是否是罪魁祸首以及是否有任何替代方法来编码表单键?