我们公司正在快速发展状态,是时候开始制定各项技术标准规范(各种技术栈的语言规范)和工作流程从开发、测试到上线等)了,否则后期越来越玩不转。
前期虽然有引进各种规范,但总是支离破碎,而且有很多地方也不太符合我们公司工程师口味,所以也没有继续执行下去。
最近我们在开始整理各种技术规范和流程,会经历以下流程:
今天我们公示一下我们公司的初稿,并解释其中的原因,也广泛征求大家的意见和建议,大家的每一条建议我们都会深入思考和论证的。后续我们还会有很多类似的规范拿出来和大家一起交流,不吝赐教。
服务端、服务端对接端(网页端、APP 端、小程序端)
{
"resultCode": 200,
"data": null,
"errorMsg": ""
}
{
"resultCode": {通用处理结果代码},
"data": null,
"errorMsg": "对应的错误消息"
}
为什么我们的返回都尽量采用 HTTP Status Code 为 200 ?
答:经过公司内部对接端同事们的意见,如果返回的是非 200 状态码,目前很多框架会在框架层直接拦截,不会进一步解析消息体,不方便拿到服务端返回的错误消息。
[重点讨论] 那为什么鉴权失败时要返回 HTTP Status Code 401 呢?
答:目前我们的 APP 中有通过 WebView 嵌套网页,网页里面又有 Ajax 的调用。
之前我们的流程是,APP 内如果需要打开网页,则需要通过一个固定的链接进行转换,例如本身要访问 a 链接,则务必访问跳转链接并添加参数 b?targetUrl=a,同时携带 APP 的鉴权参数( APP 我们是把鉴权参数放到 header 里面的),服务端拿到 APP 的鉴权信息后会回写 cookie 到网页中,同时引导跳转到真正的目标地址 。
上述流程里面就会出现一个问题,当 APP 里面的鉴权信息( Token )没有过期,但网页中的鉴权信息过期了(例如一些不可抗拒因素导致某台服务器丢失了网页端的 session ),用户再点击网页里面的内容,则始终会报告失败,给用户一种很不好的体验。
之前我们是通过 bridge 的形式由网页端通知 APP 端发起重新跳转,如果本次跳转 APP 鉴权信息依然有效则按照前述流程正常打开网页,如果本次跳转发现 APP 的鉴权信息也失效了,则引导用户在 APP 中重新登录。 根据我们的经验,bridge 这种方式很容易出现兼容性问题,在某些机型上无法通知 APP,导致用户始终卡在网页上(用户并不知道要重启 APP,只知道找客服)
为了让用户得到更好的体验,我们打算在 APP 层面捕捉 webview 的所有请求,一旦发现 HTTP Status Code 为 401 的情况,就引导 APP 重新登录,简单粗暴,不过会忽略 APP Token 有效,网页 Token 无效这种情况。
如果把 401 放到返回 body 里面,不方便 APP 统一捕捉返回信息。
如果按照上述我们的方案,我们的接口需要接收 cookie 这种鉴权方式( APP 内打开的网页通过 ajax 调用),也需要接收 header 这种鉴权方式( APP 直接请求);我们的网页需要接收 header 这种鉴权方式( APP 通过跳转链接打开目的网页时),也需要接收 cookie 这种鉴权方式(正常情况下都通过 cookie 认证)。
1
linxl 2019-10-30 15:17:22 +08:00
"为什么我们的返回都尽量采用 HTTP Status Code 为 200 ? "
这个怕是乱讲吧. 哪个框架? |
2
Vegetable 2019-10-30 15:18:22 +08:00
我们采取的方案是 h5 和 app 共用 token,打开 webview 的时候使用 webview 的某个 hook,在 url 末尾拼接 token={token},对页面进行鉴权。
页面内部的 ajax 从 url 上取当前 token,取不到自然走异常流程,能取到则正常发起 ajax 请求。 |
4
odirus OP @Vegetable 这倒是一个不错的方案
APP 跳转到网页,网页里面有 ajax 这个似乎都能够处理。那网页里面打开其他链接地址是否也可以呢?例如通过 js 拦截点击请求,把 Token 也添加到目标地址里面。 非常感谢这个方案,非常有建设性的意见。 |
5
baiyi 2019-10-30 15:23:02 +08:00
感觉接口规范的问题都要成周经贴了
我先来:用 RESTful 规范! |
6
odirus OP 另外,我刚刚和同事沟通了,网页通过 bridge 的方式通过 APP 或者小程序都比较稳定,没必要通过统一拦截返回状态码的方式来发现是否 Token 是否过期。
|
7
odirus OP @baiyi
非常感谢你的建议。 其实很多时候都不是那么理想化,推进一个东西不仅要科学,更多的时候还要考虑人为配合的问题,也许你这个方案非常好,但别人就是故意不配合,那也很尴尬的,所以我们要征得内部大多数人的赞同才行。 当然放到 V2EX 讨论是希望能够得到更多的意见和建议。 |
8
ochatokori 2019-10-30 15:36:06 +08:00 via Android 1
你确定鉴权失败要返回 401 吗…
浏览器遇到 401 会弹出那个浏览器自带的输入帐号密码的东西 |
9
star7th 2019-10-30 15:39:37 +08:00 1
不用用 http 本身的返回状态。全部状态在业务层返回(也就是返回的 json 中)。这种兼容性是最好的,而且统一。
|
10
odirus OP |
11
L1shen 2019-10-30 15:43:54 +08:00 1
make http code again
|
12
zagfai 2019-10-30 15:49:43 +08:00
嗯 我们也是这样 实践上比 restful 好 至于好在哪里 别问我。
|
13
luckyrayyy 2019-10-30 15:55:32 +08:00
到底是用 http code 还是返回值,这个真的是每次拿出来都能吵三天三夜...
|
14
SilencerL 2019-10-30 15:59:35 +08:00 1
@ochatokori #8
@odirus #10 如果需要 Status Code 返回 401 并且不想让浏览器弹窗,在 Response 的头里面去掉 [WWW-Authenticate: Basic realm="Realm"] 即可。 |
15
oott123 2019-10-30 16:41:57 +08:00
与其说这是规范,不如说这是对你们现有架构的总结。
通篇只看到说现有业务逻辑怎么怎么样,而不是设计成怎么怎么样会有什么好处或者坏处 |
16
kkkkkrua 2019-10-30 16:47:13 +08:00
怎么又是 http code 又是 body 中的 code ?
当 http code 不是 200 的时候,应该都不用关注 body 了 当 http code 为 200 的时候,body 中的 code 为业务 code restful 规范确实好,但是实现起来想达到理想状态,比较困难 |
17
warcraft1236 2019-10-30 16:50:22 +08:00
这个东西看看各种大厂的 openapi 怎么做的不就行了?
|
18
odirus OP @kkkkkrua
经过商议和讨论,我们还是希望遵循一个大原则:就是除非 Token 失效返回 HTTP Status Code 外,其他情况都返回 200,但业务在处理参数校验、未处理异常这些公共错误时,还是要通过 resultCode 传递给调用端,让他们知道是怎么回事,方便给用户进行提示。 |
20
x537196 2019-10-30 17:01:00 +08:00
在 HTTP 状态码为 200 的情况下,我们是用业务码来标记业务处理结果,如果 HTTP 状态码非 200,一律提示服务不可用
|
21
odirus OP @Vegetable
我们也做了一些讨论,觉得你的方案很不错,当 APP 访问网页时就把 token 放到链接中,当网页里面打开其他链接时也把 Token 带上。 但有一个问题,如果用户不小心把这个东西分享出去了,那就很危险了,相当于泄露了这些信息。 你们是如何处理这个问题的呢?望解答,谢谢 |
22
diferent 2019-10-30 19:32:00 +08:00 2
很简单, 就是做的系统不够大, 不够复杂,所以才会不理解 Restful. 才会觉得所有东西都放到 Body 里最简单.
Restful 的精髓就在于, 当你的系统足够复杂的时候,有 N 多层代理和路由服务时,不需要解析 Body(你也解析不起), 就可以追踪业务和进行业务分发或日志记录. |
23
Varobjs 2019-10-30 19:39:36 +08:00 via Android
每月一次
好用就是规则,大家遵守就好,没啥讨论了 |
25
mogutouer 2019-10-30 19:52:40 +08:00
去看 twitter,facebook 的 API 格式不就行了
|