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

一个关于请求与返回的数据加签的疑问

  •  
  •   x1aoYao · 2019-12-16 17:51:39 +08:00 · 1874 次点击
    这是一个创建于 1802 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原始数据:

    { 
       "id":1,
       "info":{
          "name":"x",
          "age":19
       },
       "course":[
          "math"
       ],
       "timestamp":1575174600,
       "nonce":"xxx"
    }
    

    方案 1:

    • 按 key 的字典序拼接原数据字符串,过滤掉 sign 字段:course=["math"]&id=1&info={"name":"x","age":19}&nonce=xxx&timestamp=1575174600
    • 进行签名,放入 sign 字段得到新的 json
    {
       "id":1,
       "info":{
          "name":"x",
          "age":19
       },
       "course":[
          "math"
       ],
       "timestamp":1575174600,
       "nonce":"xxx",
       "sign":"awoskedflvj"
    }
    

    方案 2:

    • 把整个 json 当作字符串进行加签
    • 将原 json 对象与签名字符串组装成一个新的 json
    { 
       "data":{
          "id":1,
          "info":{
             "name":"x",
             "age":19
          },
          "course":[
             "math"
          ],
          "timestamp":1575174600,
          "nonce":"xxx"
       },
       "sign":"xcvoawierj"
    }
    

    我只用 golang 简单验证了这样不会出错,json.RawMessage 可以很好的解决。
    想请问下这样做有什么问题没?如果方案 2 有问题,方案 1 在存在嵌套 json 的情况下也有问题。
    为什么很多地方都采用先排序再拼接的方式呢,仅仅是数据来源可能在 header 里或者 url 里之类的情况吗?

    或者有什么通用的比较好的解决方案

    7 条回复    2019-12-16 18:37:35 +08:00
    qiayue
        1
    qiayue  
       2019-12-16 17:56:59 +08:00
    排序的目的是尽量让每一次请求的签名都不一样
    x1aoYao
        2
    x1aoYao  
    OP
       2019-12-16 18:03:40 +08:00
    @qiayue 参数中加 nonce 随机字符串才是为了让签名不一致吧
    排序再拼接是为了排除 json 格式的影响吧
    kkkkkrua
        3
    kkkkkrua  
       2019-12-16 18:11:14 +08:00 via iPhone
    排序是为了消除一些传输中导致顺序更改的问题,你换成 json 的话,多一个空格你就验证不通过了
    index90
        4
    index90  
       2019-12-16 18:15:48 +08:00
    为什么不把签名信息放在 header 中?
    index90
        5
    index90  
       2019-12-16 18:23:03 +08:00
    排序再拼接,一般是用于 query 参数的处理,你无法确保 client 的签名是 key 的顺序与 server 签名时 key 的顺序一致,所以一般会约定先按 key 排序再签名
    body 的参数不应该篡改,直接当做 byte 数组进行签名
    签名信息一般放在 header 中直接提取,而不是像你例子中那样,需要反序列化之后才能提取,这样多浪费计算资源
    x1aoYao
        6
    x1aoYao  
    OP
       2019-12-16 18:33:31 +08:00
    @kkkkkrua 所以需要加签验签的时候都把 json 都做 byte 数字
    @index90 同意你的说法 body 就是整个 json,sign 放在 header
    kkkkkrua
        7
    kkkkkrua  
       2019-12-16 18:37:35 +08:00
    建议方案 1 的加密方式,sign 是否要放到 json 里,都可以,只要约定好就可以。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   980 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:09 · PVG 05:09 · LAX 13:09 · JFK 16:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.