V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Cbdy
V2EX  ›  前端开发

一个可能长期存在,但是不被注意,可能没有发生问题,但是存在隐患的问题

  •  
  •   Cbdy · 2020-09-17 11:10:29 +08:00 · 1444 次点击
    这是一个创建于 1530 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近看别人的代码,发现服务端的接口直接把数据库的实体传给了前端,这可能会导致一些隐患。

    问题

    比如某实体定义如下

    data class LogEntity(
            val id: Long,
            val desc: String
    )
    
    val logEntity = LogEntity(id = 122337203685400001L, desc = "Some description")
    

    转成 JSON 变成了

    {
      "id":122337203685400001,
      "desc":"Some description"
    }
    

    然后前端把这个 JSON parse 成 JavaScript 对象,变成了

    Object { id: 122337203685400000, desc: "Some description" }
    

    LogEntity 的 ID 个位的 1 变成了 0,出现问题了。

    这实际上是一个 JavaScript 的number类型处理数字的 feature,JavaScript 能准确表示-2^532^53之间的整数,具体可以看这个文章。然而有的语言的 Long 类型的范围是大于-2^532^53这个范围的,比如 Java 的Long的范围为-2^632^63-1,而在数据库里定义有符号的BIGINT,往往会用Long来在应用内存中表示。(当然实际实践中这么大的数字可能比较少见。)

    所以比较合适的做法是在定义一个用于传输数据到前端的 DTO,把Long转成 JSON 支持的string类型,如

    data class LogDTO(
            val id: String,
            val orderDesc: String
    )
    
    val logDTO = LogDTO(id = logEntity.id.toString(), desc = logEntity.desc)
    // {"id":"122337203685400001","desc":"Some description"}
    

    结论

    在实践中使用专门定义的 DTO 传输数据确实是一个比较好的做法。除了上述的问题,其他的如 JSON 不支持时间,可以用 ISO8601 字符串或 UNIX 时间戳,JSON 不支持byte[],可以编码成 Base64 。

    所以请不要直接向前端返回定义的用于 CURD 的数据库实体。

    2 条回复    2020-09-17 11:18:00 +08:00
    sunjiayao
        1
    sunjiayao  
       2020-09-17 11:16:09 +08:00
    更大的问题是数据泄露。
    kop1989
        2
    kop1989  
       2020-09-17 11:18:00 +08:00
    暴露给公网的 api 返回的一定得是针对 api 本身业务内容设计的 vo 也好,dto 也罢。
    因为没必要暴露全部的 domain 字段。

    至于说类型方面的序列化 /反序列化问题,谁做都行。
    后端可以针对性转换,前端也可以。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5055 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 09:48 · PVG 17:48 · LAX 01:48 · JFK 04:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.