公司项目是CMS后台管理。上线了产品告知说某某所不能上外网,上网只能用手机,所以网站要适配手机端。。。。后台只能用手机访问,好奇葩啊。所以系统要适配移动端。
还好前端用的bootstrap框架,这样页面至少样式什么的大致上不会有什么问题。就这样,项目上线了。然后用了一周后发现一个问题,手机输入表情的时候到后台,存数据库的时候报错。问题是数据库编码是utf-8,最多三个字节。而emoji表情是四个字节。。。所以报错也是正常的。试着把某个表编码改成
utf8mb4,按道理是可以得,但是复制一个表情进去,apply的时候还是报错了,所以就想着在代码里面把他过滤掉咯。
因为项目是几个人一起做的,所以每个人的编码风格略有不同。但是万变不离其宗嘛。
本着前端的所有校验都是不可信的原则,我们的php后台肯定要做好把关,不能放过任何一个敌人操作数据库。所以第一步是写一个
Listener 监听事件
注册一个services
app.manage_log_listener: class: FilterBundle\EventListener\ExpressionFilterListener arguments: ['@router'] tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse}
EventListener
public function onKernelRequest(GetResponseEvent $event) { if($event->isMasterRequest()){ $request = $event->getRequest(); $conetent = urldecode($request->getContent()); $str = preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换 '/./u', function (array $match) { return strlen($match[0]) >= 4 ? '' : $match[0]; }, $conetent); if($str != $conetent ){ throw new MessageException("输入的内容不能包含表情呦"); } } }到这里,我们的后台就肯定不会让表情进到数据库了,但是人家一输入表情就直接跳错误页面,肯定是不友好的,所以呢,我们应该在前端交互的时候提示到用户。这样就需要我们在表单提交的时候做好验证了。表单验证无非两种方法,一是form表单直接submit。一是ajax提交。由此,我们就需要写两个校验。
form表单提交
jQuery("form").submit(function (e) { var formDate = jQuery("form").serialize() ; var urlDate = decodeURIComponent(formDate); var urlDateReal = urlDate.replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, ""); if(urlDateReal != urlDate ){ alert("表单含有非法字符1"); e.preventDefault(); } })这样写呢,过滤是做到了,但是由于全局的js有不好的地方就是,当你的表单时在页面加载之后生成的话,这样js没起作用,怎么办呢?这时候就要我们jQuery的delegate 函数了。api上说1.7之后推荐优先使用on()。我没用。。。。
jQuery(".wrapper").delegate("form","submit",function(e) { var formDate = jQuery("form").serialize() ; var urlDate = decodeURIComponent(formDate); var urlDateReal = urlDate.replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, ""); if(urlDateReal != urlDate ){ if(jQuery(window).cetcmask){ jQuery(window).cetcmask('输入内容不能含有表情等非法文字21'); setTimeout("jQuery(window).uncetcmask()",1000); }else { alert('输入内容不能含有表情等非法文字'); } return false; } });这样表单提交就可以了,剩下就是ajax提交了,ajax提交前beforeSend方法校验jQuery.ajaxSetup({ beforeSend:function () { var formDate = jQuery("form").serialize(); var urlDate = decodeURIComponent(formDate); var urlDateReal = urlDate.replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, ""); if(urlDateReal != urlDate ){ if(jQuery(window).cetcmask){ jQuery(window).cetcmask('输入内容不能含有表情等非法文字ajx'); setTimeout("jQuery(window).uncetcmask()",1000); }else { alert('输入内容不能含有表情等 非法文字'); } return false; } } });大功告成!之所以js跟php用不一样的正则匹配,不是为了秀正则,而是因为这两个是我百度来的,试了下都能用,,,所以也懒得去管他了,php的是把每个字符分割,匹配到不是三个字节的就直接过滤,js是比对范围。。。。。。