RESTful 风格的验证码接口应该如何设计? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
kuoruan
V2EX    程序员

RESTful 风格的验证码接口应该如何设计?

  •  
  •   kuoruan 2019-03-21 17:11:02 +08:00 5489 次点击
    这是一个创建于 2400 天前的主题,其中的信息可能已经有所发展或是发生改变。

    URL: /api/v1/captcha

    操作分为获取验证码和验证验证码

    当前设计:

    获取验证码使用 POST URL,表示创建一个新的验证码,Content body 为

    { "id": "request id" } 

    Body 如果为空的时候,去 Header 里边取 X-Request-ID,如果都为空,则随机生成一条 UUID 作为对应的验证码 ID

    返回内容为:

    { "id": "captcha id", "data": "captcha image base64" } 

    验证验证码的时候使用 DELETE URL,因为每个验证码只验证一次,相当于删除操作。

    Content Body 内容为:

    { "id": "captcha id", "value": "captcha value" } 

    验证失败时返回 400 外加失败内容:

    { "code": 400, "message": "captcha verify failed" } 

    验证成功时返回 204 空 Body

    我第一次写 RESTful API 后端,请问各位这种设计是否符合规范?

    是否有更好设计?

    7 条回复    2019-03-21 22:28:13 +08:00
    icelzh
        1
    icelzh  
       2019-03-21 17:51:53 +08:00
    获取验证码 GET /api/v1/captcha

    请求成功
    生成
    由 captcha_code = 123 创建记录 captcha_id = 123
    返回
    captcha_id = 123 保证数据库唯一性
    captcha_image = 根据 captcha_code 生成的图片地址

    验证验证码 POST /api/v1/captcha
    captcha_code + captcha_id 进行验证

    验证状态 就是
    status ok or no_ok
    status_code 错误码
    data 就返回的数据
    success 成功的文案 不成功就为空
    errors 失败的文案 成功就为空
    index90
        2
    index90  
       2019-03-21 18:24:48 +08:00   2
    RestFul 不是规范,是一种建议,所以没有唯一答案,但有一个共同的目标,就是尽量在不阅读文字解析的情况下,只需要看 method 和 url,就知道你这个接口在做什么。

    1. 获取验证码,感觉你的方案有点技术化思维,虽然对于你后台实现来说,是生成一个验证码,但是对于调用方来说,就是获取一个验证码。接口定义应该站在使用方角度去设计,所以应该用 GET /api/v1/{request_id}/captcha。如果你们的接口规范有要求每一个请求都会有 X-Request-ID,可以简化为:GET /api/v1/captcha。

    2. 验证的时候,我习惯用 POST:POST /api/v1/{request_id}/captcha/{id} 或 POST /api/v1/captcha/{id},body 传 value。

    这里有个关键问题,RestFul 是为资源的操作而设计的,如果对于“ rpc ”类调用,很难表达“动作”,我是参考 elasticsearch 的 API 设计,他们采用在 URL 末端增加操作字段,例如:POST /api/v1/{request_id}/captcha/{id}/_validate
    mcfog
        3
    mcfog  
       2019-03-21 19:06:16 +08:00
    书院派 A
    POST captcha/ {type: image}

    200 {type: image, requestId, image, status: CAPTCHA_STATUS_INIT}

    PATCH captcha/:requestId
    {answer: 1234, status: CAPTCHA_STATUS_VERIFIED}

    200 {type: image, requestId, image, status, answer, verifyResult: {passed: true/false, error: ...}}

    note: 用更多字段表示状态以及后续追加的信息,用 PATCH 修改资源(状态) 表示验证语义

    书院派 B
    POST captcha/ {type: image}

    200 {type: image, requestId, image}

    PUT captcha/:requestId/answer
    {code:1234}

    201

    GET captcha/:requestId OR captcha/:requestId/verify-result
    {type: image, requestId, image, answer:{code:1234}, verifyResult:{passed: true/false}}

    note: 用 sub resource 代表资源的不同部分,创建 sub resource 表示验证语义

    老油条派:( restful 反模式)
    POST captcha/ {type: image}
    POST captcha/:requestId/verify

    POST 动词是典型的 restful 反模式, 胜在表达能力好,简单易懂,真香

    ----------

    PS. 个人认为拉取 captcha 不应当用 GET,因为有副作用,不能缓存,也不应该在用户没有干涉的前提下重试
    kuoruan
        4
    kuoruan  
    OP
       2019-03-21 19:22:58 +08:00
    @icelzh
    @index90
    ```接口定义应该站在使用方角度去设计``` 获取验证码从用户角度应该使用 GET,但是 GET 是一个幂等的操作,验证码的获取需要每一次访问返回不同的内容,而且浏览器会缓存 GET 请求(可以通过添加 query 的方式规避,但链接中就多了一些无意义的数据),POST 则不存在这个问题。因此我认为 GET URL 中应该添加随机 ID。

    如果直接用用户自己提供 ID 去生成验证码,可能会出现多个用户使用同一 ID 的情况,这种情况理应返回相同的内容,但是不符合验证码的接口需要,所以这个 ID 还得处理一下。

    对于 @index90 提到的在链接后边添加操作字段,确实也是一种比较好的方法,但为了保证接口的一致性,是否需要在资源操作的接口后面也加上操作字段?
    kuoruan
        5
    kuoruan  
    OP
       2019-03-21 19:42:24 +08:00
    @mcfog 感谢!

    A 方案用 PATCH 改变验证码状态的方式来做验证确实是个新奇的想法,也比较契合 POST 的添加操作。

    B 方案是多一次请求吗?而且 PUT 请求有存在则替换,不存在则创建的意思,意思就是创建一个 answer 吗?

    C 方案和 @index90 的类似,但是还是我觉得 A 比较厉害
    mcfog
        6
    mcfog  
       2019-03-21 20:01:27 +08:00 via Android
    @kuoruan put 第二次可以扔个 403 之类的,主要是创建已知 url 的(单个)资源应该用 put,post 一般是向一个集合里提交一个资源(客户端无法控制 url )让服务器返回 url
    joesonw
        7
    joesonw  
       2019-03-21 22:28:13 +08:00
    验证码不是跟着请求走的吗? 单独一个验证码验证的话. 验证完标记 session?

    RESTFul 里面, Get 不要有副作用. 创建验证码就是副作用了. POST, PUT 都好啊.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     883 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 21:18 PVG 05:18 LAX 14:18 JFK 17:18
    Do have faith in what you're doing.
    ubao msn 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