1 问题
最近遇到一个问题,前端提交的HTML模板一直无法保存,但是前端的jQuery显示已经提交。
后来一步步调试才知道,表单提交到后台时,有一层封装好的PHP基类,对POST/GET数据进行了过滤。
如果符合过滤条件,则直接exit()退出错误,所以肯定没办法提交数据。
如下是POST拦截条件:
class Safety{
private static $postFilter="\\b(and|or)\\b.{1,6}?(=|>|
// GET、COOKIE...
private static function checkAttack($value, $condition){
if(is_array($value)){
$value = implode($value);
}
if (preg_match("/" . $condition . "/is", $value) == 1){
exit();
}
}
public static function stopAttach(){
foreach($_POST as $value){
self::checkAttack($value, self::$postFilter);
}
// GET、COOKIE...
}
}
这条语句会侦测POST中的关键字and、or、in、/* */注释、
那怎么办,公共基类类不好改也是不能改的。
2 提示法
后来想到的第一个办法是,将特殊字符转义。
再前端根据后台的正则表达式,在前端建一个同样的判断,如果含有过滤字符,提示,更改后才能提交。
这里有两个难点。
第一是JS没有内置的特殊字符转义函数,得自己些函数,办法:JQuery Post转义提交HTML模板。
第二个是PHP的正则表达和JS的还不太一样,主要提现在点字符上,后来也解决:PHP和JavaScript正则匹配所有字符(包括换行符)的差异。
提交之前再用encodeURIComponent()转码一遍,再提交。
这样就可以提交了。
只是,这样一些特殊的字还是无法提交,比如update...set、/* */。
3 base64加解密
base64是通用的加解密方法,JavaScript也有现成的库可以使用,PHP更是有现成函数可用。
解决方法如下。
数据提交之前,用base64的方法加密:
var html_source = base64.encode(html_source)
这样不论什么字符,都可以提交了,都是。
然后,在PHP读取数据时,用base64_decode() 方法就可以解密了。
$html_source = str_replace(' ', '+', $html_source);
$html_source = base64_decode($html_source);
说明:这里需要把JavaScript加密的数据稍作处理,把空格替换成+,否则会有乱码。
加密后的字符串虽然会比原来的大一些,但是兼容性和完整性更佳。
所以目前使用的就是这个方案。
参考地址: