V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiangyuecn
V2EX  ›  程序员

多灾多难,今天又来了零宽字符,导致字符串手机号在数据库查询不出结果

  •  
  •   xiangyuecn ·
    xiangyuecn · 2020-11-14 14:41:13 +08:00 · 4102 次点击
    这是一个创建于 1470 天前的主题,其中的信息可能已经有所发展或是发生改变。

    昨天帖了一个 字符串首尾空格对数据库查询的影响的帖子 《发现多种数据库 group by 对字符串首尾空格的坑死人不偿命规范》 /t/724866 ,len 、length 、=、!= 、in 数据库查询均受影响,有人怪开发者怎么不去掉结尾空格就存到了数据库😂 数据是数据,不到一定需要的时候,多写一个 trim 都是在篡改用户提交的合法数据,你不能阻止别人发消息给你后面发空格吧

    今天又突然发现,微信里面复制出一个手机号,居然查询不出数据,但人肉去翻又能找到这个手机号,如:

    "13012345678‬" length=12,结尾有个 \u202C
    

    嗯,多了一个零宽的控制字符,肉眼不可见,非常难排查。

    我是不背锅的,这次这个锅要让苹果来背了,他们出品的手机系统里面复制电话号码似乎就会产生这种问题 \u202D 130123456789 \u202C 。顺利甩锅。

    打个针,估计会有人反驳:自己不做格式过滤怪谁,手机号不都是数字的吗😂

    感觉纯字符串,要处理掉非法的零宽字符还是异常困难的,至少要维护一个 Unicode 名单,和研读字符的各种控制规则,比如常见的 emoji 拼接字符:\u200D,独立出现就是非法,但在多个 emoji 字节码里面又能准确的表达一个复杂的 emoji 。简单的去掉一些黑名单字符还是可以的,比如胡乱越界显示的泰文

    周末祝大家代码无 bug,早日结尾款(或多发奖金)。

    第 1 条附言  ·  2020-11-14 16:07:58 +08:00

    只针对合法的用户输入中的非法零宽字符,比如一个搜索,可以搜名字或手机号,简单点就直接sql(伪代码):

    name like %?% or tel like ?%
    

    参数可以是名字:"李逵"!="李逵‬" 后面这个其实是"李鬼",结尾藏了一个零宽字符

    参数可以是手机号,如果是手机号就完全是精准前缀匹配,但并不会去做特殊格式校验(虽然可以做),小系统里面这种简单查询没必要这么细致操作,浪费时间又没工钱😂

    17 条回复    2020-11-15 23:09:41 +08:00
    debuggerx
        1
    debuggerx  
       2020-11-14 14:52:25 +08:00   ❤️ 1
    chinvo
        2
    chinvo  
       2020-11-14 14:52:38 +08:00   ❤️ 2
    但是手机号这种东西本身就不会有空格, 为什么不 trim

    你这话说的就跟 UCG 得留着 XSS 不被利用不处理一样怪
    laminux29
        3
    laminux29  
       2020-11-14 14:55:25 +08:00
    经验问题。

    1.要不要对用户输入的数据,做格式化处理,要看情况。

    2.如果数据库需要保存的是手机号码,那么这种情况是需要对用户输入的数据进行格式化处理的,而且是需要按照手机号码规范进行处理。那些不在规范里的字符,比如零宽字符,在入库前就需要处理掉。
    holulu
        4
    holulu  
       2020-11-14 15:45:24 +08:00
    要假设所有外部输入都可能出问题才对吧。
    heyjei
        5
    heyjei  
       2020-11-14 15:56:44 +08:00
    不只是苹果手机,我在 windows 10 里复制文字也 经常出现这种不可见的,但又不是零宽的字符
    yyid
        6
    yyid  
       2020-11-14 16:02:31 +08:00
    linux 文本在 windows 编辑器打开。\n 被改成 \r\n 了。。。一堆坑
    zjsxwc
        7
    zjsxwc  
       2020-11-14 16:12:08 +08:00
    @chinvo 貌似普通 trim 默认只能 把空格 tab 换行删掉,这个还干不掉。
    xiangyuecn
        8
    xiangyuecn  
    OP
       2020-11-14 16:15:01 +08:00
    @debuggerx #1 看了一下,发现他对 emoji \u200D 连接过的 处理也是一个难题,还是 todo 中😂
    lucybenz
        9
    lucybenz  
       2020-11-14 16:15:18 +08:00
    为赋新词强说愁
    xiangyuecn
        10
    xiangyuecn  
    OP
       2020-11-14 16:28:14 +08:00
    @lucybenz #9 哈,被你发现了,10 年专业造词,别人绝对看不懂😂
    xuanbg
        11
    xuanbg  
       2020-11-14 17:24:03 +08:00
    不合法的空格当然要处理掉啊。用户输入是不可信的,必须要进行合法性验证。没弹框警告非法字符,悄悄处理掉多余空格已经算是照顾用户体验了好吧。
    dblpx
        12
    dblpx  
       2020-11-14 18:29:44 +08:00 via iPhone
    涨知识了,谢谢楼主
    abc612008
        13
    abc612008  
       2020-11-14 18:48:15 +08:00
    tel like ?%那输入个 1 不就能爆出所有手机号了
    xiangyuecn
        14
    xiangyuecn  
    OP
       2020-11-14 19:00:06 +08:00
    @xuanbg #11 @abc612008 #13 唯有苦笑而不语😏
    JerryCha
        15
    JerryCha  
       2020-11-15 11:53:26 +08:00
    已知中国内地的手机号都是 11 位
    于是不以+86 开头的输入直接判断是不是 11 位,不是就给老子爬
    azh7138m
        16
    azh7138m  
       2020-11-15 18:15:26 +08:00
    微信老问题了
    手机号入库得做 trim 的
    longaiwp
        17
    longaiwp  
       2020-11-15 23:09:41 +08:00
    这是一个常见问题,在很多系统里都会出现,当然可能应用内也有自己的处理,就是怎么去处理 BiDi,也就是去处理字的方向。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2720 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:01 · PVG 12:01 · LAX 20:01 · JFK 23:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.