开放 api 接口,如何做签名验证? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
leiuu
V2EX    程序员

开放 api 接口,如何做签名验证?

  •  
      leiuu 2019-10-16 10:39:50 +08:00 8661 次点击
    这是一个创建于 2189 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RT。

    V 友好,想请教一个问题。

    场景是这样的,我需要暴露一个 api 给第三方,第三方有可能会把这个 api 放到公开网站中。

    如果没有做签名校验的话,可能爬虫 /任何人都能触发这个链接,这会导致系统会有很多非法的请求,进而带来系统数据异常等其他损失。

    针对这类问题,大家一般会用什么方法去解决?

    40 条回复    2019-10-19 10:50:58 +08:00
    Balthild
        1
    Balthild  
       2019-10-16 10:46:19 +08:00
    hmac 算法,对 URI + Body 签名
    yoshiyuki
        2
    yoshiyuki  
       2019-10-16 10:49:13 +08:00   1
    1,生成密钥 key
    2,要求客户端调用的时候,带上自己的密钥 id,并用参数转字符串后拼接密钥,md5 后得到签名
    3,服务端校验签名
    arrow8899
        3
    arrow8899  
       2019-10-16 10:49:26 +08:00   4
    签名在这里没用吧,对方也可能把签名算法公开出去。
    可以用 IP 白名单,限制第三方服务器特定的 IP 才能访问。
    laravel
        4
    laravel  
       2019-10-16 10:50:38 +08:00
    oauth 啊,给他一个 appid appsecret 他可以用这俩获取 access token (有过期时间的),微信公众平台 等不都是这样的吗
    CantSee
        5
    CantSee  
       2019-10-16 11:04:30 +08:00
    微信 银联 支付宝的不是有现成的例子啊!
    U7Q5tLAex2FI0o0g
        6
    U7Q5tLAex2FI0o0g  
       2019-10-16 11:06:28 +08:00
    一般的解决方案就是 OAuth 2.0
    xiaoyangsa
        7
    xiaoyangsa  
       2019-10-16 11:17:00 +08:00   2
    收费,按调用次数。。。
    leiuu
        8
    leiuu  
    OP
       2019-10-16 11:19:19 +08:00
    @yoshiyuki 这个看起来合理。还有一个小问题,如何防止这个带签名的链接被暴露后重复调用?
    leiuu
        9
    leiuu  
    OP
       2019-10-16 11:20:08 +08:00
    @Balthild 感谢,我了解一下。
    0NF09LJPS51k57uH
        10
    0NF09LJPS51k57uH  
       2019-10-16 11:22:08 +08:00
    hmac 算法对 query params + timestamp + secret key 进行签名,服务器端用同样算法进行验签。
    leiuu
        11
    leiuu  
    OP
       2019-10-16 11:22:35 +08:00
    @littleylv
    @laravel
    @littleylv

    都推荐了 OAuth,我了解一下。
    leiuu
        12
    leiuu  
    OP
       2019-10-16 11:22:50 +08:00
    @xiaoyangsa 不行
    xiaoyangsa
        13
    xiaoyangsa  
       2019-10-16 11:25:28 +08:00
    @leiuu
    那就学微信的公众号登录授权吧。这个靠谱点。
    leiuu
        14
    leiuu  
    OP
       2019-10-16 11:25:53 +08:00
    @CantSee 求详解。

    @arrow8899 ip 白名单的话可能不太好弄,假设这个 api 要面对几百几千个第三方。用签名的方法的话, 如果被公开的话确实没什么好的办法。只能走商务路径了哈哈哈哈。
    shadow88sky
        15
    shadow88sky  
       2019-10-16 11:29:18 +08:00
    就是 Oauth 认证 不用想
    unco020511
        16
    unco020511  
       2019-10-16 11:31:16 +08:00
    请参考微信支付宝,蛮简单
    waterlaw
        17
    waterlaw  
       2019-10-16 11:32:14 +08:00 via Android
    之前公司用第三方的接口,Oauth + 签名
    anyforever
        18
    anyforever  
       2019-10-16 11:33:37 +08:00
    如果对方想公开密钥,你用什么签都没用啊,相当于人家把钥匙丢了,而你这锁又没换,捡到钥匙的当然可以随时开你的锁了。所以避免别人丢钥匙,你就得给他加个 IP 验证
    fancy111
        19
    fancy111  
       2019-10-16 11:34:25 +08:00
    既然都放到公开网站上了,加密签名授权什么的都是没用的。既然网页能调用,我利用链接一样可以。
    唯一就是加白名单了,具体情况你没说清楚。
    eason1874
        20
    eason1874  
       2019-10-16 11:41:29 +08:00
    最好的校验方法是加几个参数,timestamp、appid 和 sign(除 sign 以外所有参数按字母升序排序,密钥)。

    再加上 IP 白名单是最安全的,不过这个不是什么场景都有条件。
    ericgui
        21
    ericgui  
       2019-10-16 11:44:31 +08:00
    @Balthild github 就是用这个
    fengxianqi
        22
    fengxianqi  
       2019-10-16 11:47:01 +08:00
    阔以参考微信服务器的做法,我之前就是这么做的。
    timestamp,appid,appsecret,nonce 生成一个 signature,通过 timestamp 可以让 url 在某段时间失效,通过 nonce 可以防止重放攻击。微信公众号文档参考: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
    ochatokori
        23
    ochatokori  
       2019-10-16 11:50:13 +08:00 via Android
    不管你怎么认证对方都可以开放给其他人使用吧,最差就他做一个转发

    实际点就按次数收费或者限制调用次数,次数不够了让对方联系提供正当理由增加次数
    CRUD
        24
    CRUD  
       2019-10-16 11:52:29 +08:00
    1、生成一个签名 key,MD5 对 body+time+key 计算摘要作为签名。
    2、RSA,交换公钥,用自己的私钥签名,用对方公钥进行报文加密,相对比较麻烦。
    3、oauth。
    luckyc
        25
    luckyc  
       2019-10-16 12:00:53 +08:00
    第三方有可能会把这个 api 放到公开网站中。

    溜了溜了, 你自己玩微信公众号么?
    你把你的 appid appsecret 暴露出来看看..这机密都能随意泄露, 那你怎么加密都没啥用.
    markgor
        26
    markgor  
       2019-10-16 12:04:46 +08:00
    @l4ever appid appsecret 露出,在好像也什危害了吧...
    微信 JSSDK 或 Oauth 在需要自行配置域名和 IP 白名。
    yoshiyuki
        27
    yoshiyuki  
       2019-10-16 13:17:14 +08:00
    @leiuu 可以加上一个时间参数,近 5s 内的时间戳有效,时间戳参与签名计算,另外,密钥发放的时候,需要绑定 ip 白名单
    leiuu
        28
    leiuu  
    OP
       2019-10-16 14:10:21 +08:00
    @unco020511 蟹蟹
    @shadow88sky 蟹蟹

    @anyforever 这么讲我就明白了,哈哈哈

    @fancy111 场景的话其实是想用于广告监测,比如用户打开一个页面,成功加载一个广告,算一次广告展现,把这条信息发送给多个监测方,我们是其中一个。
    leiuu
        29
    leiuu  
    OP
       2019-10-16 14:13:33 +08:00
    @eason1874 这个方法靠谱!比较清楚了哈哈哈。


    @ericgui 蟹蟹


    @fengxianqi 我现在去看看


    @ochatokori 有道理!


    @CRUD 给力!!


    @l4ever @markgor 明白了 哈哈哈 你俩掰扯掰扯



    @yoshiyuki 靠谱!!
    murmur
        30
    murmur  
       2019-10-16 14:20:42 +08:00
    不暴露接口的直接随便 hash 一签都很安全
    放到 app 里不需要登录的只要数据够值钱怎么都不安全
    markgor
        31
    markgor  
       2019-10-16 14:26:33 +08:00   1
    ememe,什好扯的, @l4ever 所大,安全事肯定要注意。
    我想表的是你考微信,初 oauth 就可何後面加入百名。
    按算 5s 内的时间戳有效 方式有平台在用,他的技人到不敢吭。(你想象下的延和的不同步因素),後他技改不一致後返回相差。(不用想了,又被人了一次,既然你都返回相差,你 TM 不如直接跳?)

    如有可能 IP 白名即可了。不用那多花花的。
    gongshishao
        32
    gongshishao  
       2019-10-16 14:31:38 +08:00
    阿里奇门规范了解一下,开放接口的常规加密手段
    leiuu
        33
    leiuu  
    OP
       2019-10-16 15:45:10 +08:00
    @markgor 同意!白名单方式具备条件的话是最好用。
    还有一个小问题,微信的验证方式,假设我将携带 signature 的链接暴露出来,同样会触发攻击吧?
    markgor
        34
    markgor  
       2019-10-16 16:01:13 +08:00   2
    @leiuu
    微信方式:
    比如提交是:
    name="abc"
    age = 18

    假 appid : 12345678
    假 appsecret: abcdefg

    此根生成一 timeStamp = 123456789
    生成一串字符:nOnseStr= a456sdf

    名方法:
    根排序,文本合:
    signature = md5('age=18&appid=12345678&name=abc&noseStr=a456sdf'.abcdefg)//大致吧具忘了

    然後可以得出,
    如果篡改上面任意一,最的 signature 容是不符的。
    上面件,只有 age,name,timeStamp,nonseStr 是人知道的,缺少了 appid 和 appsecret ,
    因 timeStamp 是一直的,nonseStr 也是生成的,如果通截包方式猜 appid 和 appsecret 明困。(然不排除有人直接固定 timestamp 和 nonseStr 的容)
    所以就算 signature 或者 每次的求被人截了,想篡改可能不大。

    什後面微信有白名呢。
    那是因有很多者把 appid 和 appsecret 都上 github 去了。
    所以後面通的公取 accessToken 都要置 IP 白名。
    markgor
        35
    markgor  
       2019-10-16 16:09:31 +08:00   1
    吧,
    如果你直接修改提交的容,但是 signature 不改,微信那的候直接就不通了,因你需要用被修改的重新跑一次加密的程,才能得出正的 signature (微信也是用得到的根相同的公式行名,再比名是否一致)
    什需要字符和截加去,就是了行混,增加解密度(解出 appsecret 的度)。


    後期何定 IP,
    那是因太多人的 appid 和 appsecret 露出去了。
    Leigg
        36
    Leigg  
       2019-10-16 17:02:15 +08:00 via Android
    你自己把方案都说出来了。
    Guidarin
        37
    Guidarin  
       2019-10-16 17:44:59 +08:00   1
    如果这个 API 只是给某个特定的合作方来使用,那就约定 secret key 用 Https + 签名 + IP 白名单,没必要用 oauth 协议,
    另外做好调用频率限制,看业务确定是否允许重载
    Ps: 有老牌的短信服务商,对外提供服务就喜欢使用 IP 白名单
    balabalaguguji
        38
    balabalaguguji  
       2019-10-16 20:41:58 +08:00
    这里有个签名算法,其实就是跟微信支付的一样的: https://easydoc.xyz/#/s/17790664/CZMqMhfW/72093984
    saltedFish666
        39
    saltedFish666  
       2019-10-17 17:17:32 +08:00
    最简单,IP 白名单啊
    abellee000
        40
    abellee000  
       2019-10-19 10:50:58 +08:00 via Android
    用 hmac 的 app 逆向过两个 唔 伪造起来还是挺简单的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2552 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 15:31 PVG 23:31 LAX 08:31 JFK 11:31
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86