簡說:Web API 設(shè)計指南

檢查清單

  • URI是否短小且容易輸入
好的例子:http://api.example.com/search
壞的例子:http://api.example.com/service/api/search狭握。

域名已經(jīng)是api,在URI就沒有必要重復(fù)一些毫無意義的單詞。
  • URI是否能讓人一眼看懂
不要輕易使用縮寫:http://api.example.com/sv/u
使用更地道的英語表達踪栋,比如搜索接口一般用search而不是find肺然,可以多參照一些國外大廠的API贸辈。
  • URI是否只有小寫字母組成
HTTP協(xié)議指定了:URL中除了schema和hostname不區(qū)分大小寫泪姨,其他部分均大小寫敏感凸椿。
因此削祈,URI應(yīng)該使用小寫,禁止大小寫混寫脑漫。
  • URI是否容易修改
比如獲取某個商品信息的URI應(yīng)該長這樣:http://api.example.com/v1/items/12346
從URI直觀的即可知道獲取56780商品的URI是這樣:http://api.example.com/v1/items/56780岩瘦。

開發(fā)者對URI的行為理解是自然的,不費心的窿撬。
  • URI是否反映了服務(wù)端的架構(gòu)
不要暴露服務(wù)端是哪種開發(fā)語言启昧,下面是錯誤的例子:
http://api.example.com/cgi-bin/get_user.php?user=100
  • URI規(guī)則是否統(tǒng)一
URI中的詞匯和結(jié)構(gòu)應(yīng)該保持統(tǒng)一。

下面是一個錯誤的例子:

獲取好友信息:http://api.example.com/friends?id=100
發(fā)送信息:http://api.example.com/friend/100/messages

首先劈伴,friends和friend的單復(fù)數(shù)形式不統(tǒng)一密末,你可以想象API使用者是如何被這種細小的差異坑了半天。
其次跛璧,一個通過get參數(shù)傳參严里,一個通過URI路徑傳參,不夠統(tǒng)一追城。

一個正確的例子:
獲取好友信息:http://api.example.com/friends/100
發(fā)送信息:http://api.example.com/friends/100/messages

該例子遵循REST風(fēng)格刹碾,下面講解REST URI設(shè)計風(fēng)格。

  • 有沒有使用合適的HTTP方法
作者強調(diào)REST風(fēng)格座柱。

HTTP方法表示"進行怎樣的操作"迷帜,URI表示"資源",HTTP和URI一起則表示"對什么資源做什么操作"色洞。

GET:獲取資源

獲取ID=100的好友信息戏锹,
GET http://api.example.com/friends/100

POST:新增資源

添加一位好友,相當(dāng)于新建一個好友關(guān)系:
POST http://api.example.com/friends

PUT:更新已有資源

更新ID=100的好友信息(例如:更新備注信息)火诸,
PUT http://api.example.com/friends/100

PATCH:更新部分資源

和PUT類似锦针,只是強調(diào)更新資源的部分信息,不常用。

DELETE:刪除資源

刪除ID=100的好友信息:
DELETE http://api.example.com/friends/100

HEAD:獲取資源的元信息

這個作者沒有詳細去說一個資源的元信息應(yīng)該是什么樣的奈搜。

感覺和自己設(shè)計的API不太一樣吧悉盆?這就是REST風(fēng)格,常見于國外各種大廠馋吗。
  • URI里用到的單詞所表達的意思是否和大部分API相同
有點重復(fù)舀瓢,還是強調(diào)對于非英語母語的開發(fā)者,應(yīng)該注意使用地道準(zhǔn)確的單詞耗美。
比如,照片應(yīng)該用photo而不是picture航缀。
  • URI里用到的名詞是否采用了復(fù)數(shù)形式
因為URI表示資源的集合商架,所以作者是建議總是使用復(fù)數(shù)形式。

正確的例子:http://api.example.com/friends/100
錯誤的例子:http://api.example.com/friend/100

另外芥玉,因為REST風(fēng)格強調(diào)URI是資源蛇摸,所以不應(yīng)該在URI里出現(xiàn)動詞,因為動作是HTTP方法表達的灿巧。

錯誤的例子:http://api.example.com/get_friend?id=100
  • URI里有沒有空格符以及需要編碼的字符
URL是會被urlencode編碼的赶袄,所以不要在URI里使用空格(會被編碼成+)、UTF-8字符抠藕、亂七八糟的符號等饿肺。

即不要影響URI的可讀性。
  • URI里的單詞和單詞之間有沒有使用連接符
因為URL中的hostname不允許使用下劃線盾似,所以作者建議URI部分總是使用連字符-來連接多個單詞敬辣。
  • 分頁的設(shè)計是否恰當(dāng)
分頁參數(shù)分2種風(fēng)格,可以按情況使用:

第一種零院,表示第3頁溉跃,每一頁50條:
page=3&per_page=50

第二種:表示從100條開始的50條:
offset=100&limit=50

前者page從1開始增長,后者offset從0開始增長告抄。

前者對用戶來說自由度較低撰茎,緩存命中率較高。
后者對用戶來說自由度較高打洼,緩存命中率較低龄糊。

上述翻頁風(fēng)格稱為"相對位置",深度翻頁性能差(可以自己擴展學(xué)習(xí))募疮,如果數(shù)據(jù)集合有更新绎签,則翻頁時可能看到重復(fù)內(nèi)容或者錯過一些內(nèi)容。

與之相對的是"絕對位置"酝锅,即指定last_id之前的N條數(shù)據(jù)诡必,下次使用新的last_id繼續(xù)獲取。(個人理解瀑布流頁面比較適合)

  • 登錄有沒有使用OAuth2.0
很常見的認證規(guī)范,讓用戶通過大廠的賬號系統(tǒng)登錄爸舒,并授權(quán)給第三方獲取用戶信息的權(quán)限蟋字。

作者表達的意思是你如果對外提供API,應(yīng)該提供OAuth2.0認證扭勉,這樣第三方調(diào)用API時攜帶access_token鹊奖,我們即可校驗其是否有權(quán)使用API。

最后涂炎,作者描述了一下REST API的幾個等級:

REST LEVEL0:使用HTTP
REST LEVEL1: 引入資源的概念
REST LEVEL2:引入HTTP動詞(GET/POST/PUT/DELETE等)
REST LEVEL3:引入HATEOAS概念

本書是REST LEVEL2忠聚。

LEVEL3中的HATEOAS概念尚未普及,其思路是API返回的數(shù)據(jù)中應(yīng)該包括下一步行為對應(yīng)的URI是什么唱捣,客戶端請求下一步的URI就可以得到進一步的數(shù)據(jù)两蟀。

比如文章列表的返回值:

{
    "articles": [
        {
            "title": "good",
            "uri": "https://api.example.com/v1/articles/12345",
            "rel": "article/detail"
        }
    
    ]

}

每一篇文章的uri告知客戶端如何獲取文章詳情,屬于一種高度靈活震缭。


  • 響應(yīng)數(shù)據(jù)格式有沒有使用JSON作為默認格式
越簡單的東西越容易普及赂毯,JSON比XML簡單的多,也滿足需求拣宰,另外Javascript天然支持json党涕。

客戶端沒有明確指定返回值格式的話,JSON應(yīng)該作為默認的返回值格式巡社。
  • 是否支持通過查詢參數(shù)來指定數(shù)據(jù)格式
如果服務(wù)端支持多種返回數(shù)據(jù)格式膛堤,那么客戶端可以指定。

通過get參數(shù):
https://api.example.com/v1/users?format=xml

通過擴展名:
https://api.example.com/v1/users.xml

通過HTTP頭部:
GET /v1/users
Host: api.example.com
Accept: application/xml

作者建議首先使用HTTP頭部晌该,因為更符合HTTP協(xié)議規(guī)范骑祟;其次使用查詢參數(shù),避免使用擴展名气笙。
  • 是否支持不必要的JSONP
JSONP可以實現(xiàn)跨域HTTP調(diào)用次企,其原理是基于<script>加載一段服務(wù)端的javascript代碼(自行擴展學(xué)習(xí))。

API如果決定支持JSONP潜圃,可以在服務(wù)端判定客戶端是否上傳了callback參數(shù)缸棵,如果上傳了就返回jsonp格式。

客戶端為了區(qū)分不同的JSONP調(diào)用谭期,需要為每個JSONP調(diào)用生成一個唯一的全局回調(diào)函數(shù)名堵第,這一點Jquery可以幫我們實現(xiàn)。

出于正確性與安全性考慮隧出,JSONP服務(wù)端返回時應(yīng)該設(shè)置Content-Type: application/javascript而不是application/json踏志,因為返回的是一段js函數(shù)調(diào)用代碼。

作者提到胀瞪,JSONP因為是作為一個script引入的针余,服務(wù)端可以通過2種方式返回錯誤信息:
1)在json響應(yīng)體里放置error信息
2)在callback之外支持error_callback傳參
  • 響應(yīng)數(shù)據(jù)的內(nèi)容能不能從客戶端指定
有時調(diào)用方只需要部分信息饲鄙,比如:用戶信息接口只希望獲取用戶ID,這樣可以節(jié)約通訊量圆雁。

此類接口可以通過類似fields的get參數(shù)來指定返回哪些信息:
http://api.example.com/v1/users/12345?fields=name,age

另外也可以提前準(zhǔn)備幾種返回值的組合忍级,稱為響應(yīng)群(response group),比如:
http://api.example.com/v1/users/12345?group=basic_info
其中伪朽,basic_info表示返回用戶的基礎(chǔ)信息轴咱,例如name和age。
  • 響應(yīng)數(shù)據(jù)中是否存在不必要的封裝
作者出于rest風(fēng)格原因烈涮,建議把錯誤碼和錯誤信息放在http header里朴肺,而不是放在body里。

一個錯誤的例子:
HTTP/1.1 200 OK
{
    "error_code": 500,
    "error_msg": "參數(shù)錯誤",
    "data": {}
}
作者認為HTTP返回200坚洽,但內(nèi)容卻表達了500失敗戈稿,這樣很奇怪,很不rest酪术。

rest風(fēng)格更建議用下面這種方式:
HTTP/1.1 500 參數(shù)錯誤
{
    "data": {}
}
  • 響應(yīng)數(shù)據(jù)的結(jié)構(gòu)有沒有盡量做到扁平化
不要在JSON中增加無意義的多余層級,盡可能扁平化翠储。

一個錯誤的例子:

{
    "id": 12345,
    "name": "hahaha",
    "profile": {
        "birthday": "0203",
        "gender": "male",
        "language": ["zh", "en"]
    }
}

增加profile并沒有帶來什么價值绘雁,不如扁平化:
{
    "id": 12345,
    "name": "hahaha",
    "birthday": "0203",
    "gender": "male",
    "language": ["zh", "en"]
}

不僅訪問起來方便,而且傳輸?shù)膬?nèi)容也少了援所。
  • 響應(yīng)數(shù)據(jù)有沒有用對象來描述庐舟,而不是用數(shù)組
作者建議JSON返回值總是使用{}作為返回值的最外層,而不要直接返回數(shù)組[]住拭。

正確的例子:
{
    "articles": [
        {"id": 1},
        {"id": 2}
        ...
    ]
}
錯誤的例子:
[
    {"id": 1},
    {"id", 2}
]

這樣做有2個次要的理由:
1挪略,因為從字面看,articles能直接表達數(shù)據(jù)的含義
2滔岳,客戶端在處理JSON應(yīng)答時杠娱,可以統(tǒng)一將最外層作為對象去解析,不需要為數(shù)組做適配谱煤。
3摊求,有一些安全性考慮,后面會提到刘离。

  • 響應(yīng)數(shù)據(jù)的名稱所選用的單詞的意思是否和大部分API相同
對非英語母語的人室叉,多模仿大廠使用的常見單詞。
  • 響應(yīng)數(shù)據(jù)的名稱有沒有用盡可能少的單詞來描述
關(guān)于用戶注冊時間字段硫惕,

錯誤的例子:userRegistraionDataTime
這個單詞太長了茧痕,很容易打錯,也不容易記憶恼除。

正確的例子:registeredAt
  • 響應(yīng)數(shù)據(jù)的名稱由多個單詞連接而成時踪旷,連接方法在整個API里是否一致
有幾種連接單詞的方法:
1,user_id:蛇形法
2,user-id:脊柱法
3埃脏,userId:駝峰法

在JSON和Javascript中搪锣,都是建議使用駝峰法的,但是保持風(fēng)格一致是最重要的彩掐。
  • 響應(yīng)數(shù)據(jù)的名稱有沒有使用奇怪的縮寫形式
盡量避免奇怪的縮寫构舟,比如timezone寫成tz。

如果出于數(shù)據(jù)量大小的考慮而采用縮寫堵幽,屬于特殊情況狗超。
  • 響應(yīng)數(shù)據(jù)的名稱的單復(fù)數(shù)形式是否和數(shù)據(jù)內(nèi)容相一致
只為數(shù)組采用復(fù)數(shù),比如friends朴下。
其他情況使用單數(shù)努咐。

一致的命名風(fēng)格,API使用者會順其自然殴胧,養(yǎng)成習(xí)慣渗稍。
  • 出錯時響應(yīng)數(shù)據(jù)中是否包含有助于客戶端剖析原因的信息
出錯時,響應(yīng)信息應(yīng)該包含2部分:
1团滥,錯誤碼
2竿屹,錯誤原因

作者建議使用http header返回錯誤碼,每種錯誤碼的含義如下:

1xx:消息
2xx:成功
3xx:重定向
4xx:客戶端原因引起的錯誤
5xx:服務(wù)端原因引起的錯誤

而不是在JSON中設(shè)置一個error_code字段灸姊,因為http code本身就是這個意思拱燃。

當(dāng)http code為4xx或者5xx時,需要進一步告知客戶端錯誤原因力惯,這時候有2種做法:
1碗誉,在http header里自定義一些頭部信息,保存錯誤原因父晶,例如:
X-ERROR-MESSAGE: params error
2哮缺,在body中返回JSON格式的錯誤信息:
{   
    "errors": [
        {
            "message": "參數(shù)fields錯誤"
        },
        {
            "message": "參數(shù)last_id錯誤"
        }
    ]
}
作者建議采用第2種方式,因為可以描述多個錯誤原因甲喝,并且很多大廠都是這么做的蝴蜓。

  • 出錯時有沒有返回HTML數(shù)據(jù)
當(dāng)服務(wù)端發(fā)生錯誤時,很多web框架會打印一個html錯誤信息頁面俺猿。

對于API來說茎匠,當(dāng)發(fā)生錯誤時也應(yīng)該返回一個合法的JSON結(jié)構(gòu),因為客戶端假設(shè)服務(wù)端返回JSON押袍,返回HTML可能導(dǎo)致異常诵冒。
  • 有沒有返回合適的狀態(tài)碼
這一條規(guī)則有點重復(fù),主要是指返回適當(dāng)?shù)膆ttp code谊惭。
  • 服務(wù)器端在維護時有沒有返回503狀態(tài)碼
當(dāng)服務(wù)器需要停機維護時汽馋,按照Google爬蟲的建議侮东,應(yīng)該返回503錯誤碼,并且在header中告知維護的結(jié)束時間:

503 Service Temporarily Unavailable
Retry-After: Mon, 2 Dec 2013 03:00:00 GMT

這遵循HTTP1.1規(guī)范豹芯,客戶端需要實現(xiàn)邏輯去識別這個情況悄雅,但是至少google爬蟲會去理解這些信息。
  • 有沒有返回合適的媒體類型
有的HTTP客戶端會校驗應(yīng)答中的Content-Type字段铁蹈,因此服務(wù)端如果返回的是JSON宽闲,那么就應(yīng)該返回Content-Type: application/json而不是Content-Type: text/html,這樣避免一些嚴(yán)格的客戶端出現(xiàn)解析失敗握牧。
  • 必要時能不能支持CORS
瀏覽器有同源策略容诬,禁止跨域Ajax請求。

API可以支持CORS跨域資源共享沿腰,比如http://www.example.com請求http://api.example.com的API時應(yīng)該攜帶請求的來源:
Origin: http://www.example.com

服務(wù)端只允許某些來源的跨域調(diào)用览徒,如果Origin合法就在返回中攜帶:

Access-Control-Allow-Origin: http://www.example.com
或者
Access-Control-Allow-Origin: *

瀏覽器看到這樣的應(yīng)答,就會把ajax請求正常執(zhí)行完成颂龙,否則會報告ajax調(diào)用失敗习蓬。

對于一些特殊場景,瀏覽器會采用"事先請求"的方式措嵌,先通過一個OPTION方法調(diào)用到對應(yīng)的接口來試探服務(wù)端是否返回Access-Control-Allow-Origin躲叼,如果沒有返回則不發(fā)起真正的數(shù)據(jù)請求。

CORS客戶端默認不會傳輸cookie铅匹,我們在發(fā)起ajax前設(shè)置XHTTPRequest.withCredentials=true押赊,并且服務(wù)端必須返回header:Access-Control-Allow-Credentials: true饺藤,否則這次ajax調(diào)用將報告失敗包斑。
  • 有沒有返回Cache-Control、ETag涕俗、Last-Modified罗丰、Vary等首部以便客戶端采用合適的緩存策略
緩存模型分2種:
1,過期模型:Expires再姑、Cache-Control
2萌抵,驗證模型:Last-Modified、ETag

過期模型是指元镀,瀏覽器在過期之間直接使用本地緩存文件绍填,下面是一個例子:
Expires: Fri, 01 Jan 2016 00:00:00 GMT
Cache-Control: max-age=3600

Cache-Control是HTTP1.1協(xié)議出現(xiàn)的,Expires是HTTP1.0栖疑,前者優(yōu)先級更高讨永。
并且HTTP1.1協(xié)議也規(guī)定,緩存時間不應(yīng)超過1年遇革,但實際上客戶端可能沒有遵循這個約束卿闹。

驗證模型是指揭糕,客戶端照常發(fā)起請求,但在header中攜帶附加條件锻霎,服務(wù)器根據(jù)附加條件判斷若數(shù)據(jù)沒有修改則返回304著角,客戶端直接使用本地緩存即可,否則返回200并攜帶內(nèi)容旋恼。

下面是個例子吏口,

請求:
GET /v1/users/12345
If-Modified-Since: Tue, 01 Jul 2014 00:00:00 GMT
If-None-Match: "ff39b31e285573ee373af0d492aca581"
應(yīng)答:
HTTP/1.1 304 Not Modified
Last-Modified: Tue, 01 Jul 2014 00:00:00 GMT
ETag: "ff39b31e285573ee373af0d492aca581"

需要注意ETag分為強驗證和弱驗證:
強驗證是指資源的真實內(nèi)容完全不能變,弱驗證是指邏輯上資源沒有改變即可蚌铜。
  • 不想緩存的數(shù)據(jù)有沒有添加Cache-Control: no-cache首部信息
如果不希望被客戶端緩存锨侯,可以指定Cache-Control: no-cache。

如果你的API前面存在反向代理緩存冬殃,可以額外聲明Cache-Control: no-store囚痴,這樣代理服務(wù)器也不會緩存數(shù)據(jù)了。

客戶端可能多次請求同一個API审葬,但是請求的http header不同深滚,導(dǎo)致返回的內(nèi)容結(jié)構(gòu)不同,比如:

客戶端攜帶 Accept: application/json涣觉,則服務(wù)端返回的是JSON痴荐。
客戶端攜帶 Accept: application/xml,則服務(wù)端返回的是XML官册。

如果反向代理根據(jù)URI緩存生兆,則會導(dǎo)致無法根據(jù)客戶端的要求返回正確格式,此時我們API應(yīng)該在返回值里攜帶Vary: Accept膝宁,這樣緩存服務(wù)器會為不同的Accept分別緩存鸦难。
  • 有沒有對API進行版本管理
一般API會不斷的迭代功能,有時會出現(xiàn)無法向下兼容的情況员淫。

通常老客戶端會依舊使用老版本的API合蔽,新客戶端使用新版本的API,并在合適的時機完全下線掉老版本的API介返。
  • API版本的命名有沒有遵循語義化版本控制規(guī)范
作者介紹了語義化版本控制拴事,通常版本號是a.b.c這樣的,分別表示主版本號圣蝎,次版本號刃宵,補丁版本號。

1徘公,如果軟件API沒有變更牲证,只是修復(fù)服務(wù)端BUG,那么就增加補丁版本號
2步淹,對軟件API實施了向下兼容的變更从隆,增加次版本號
3诚撵,對軟件API實施了不向下兼容的變更時,增加主版本號

  • 有沒有在URI里嵌入主版本編號键闺,并且能夠讓人一目了然
對于Web API來說寿烟,作者建議在URI中嵌入主版本號即可,例如:
http://api.example.com/v1/users

整體原則是辛燥,盡量保持向下兼容筛武,這樣URI不會改變,老用戶不需要遷移挎塌。

還有一個問題是徘六,如果不帶版本號訪問應(yīng)該套用哪個版本的接口?谷歌的做法是使用最老版本榴都,這樣就不會影響那些老用戶了待锈。
  • 有沒有考慮API終止提供時的相關(guān)事項
停止API時應(yīng)該讓API返回410錯誤碼,它代表接口不再對外公開嘴高。

如果客戶端是公司的產(chǎn)品竿音,則可以強制客戶端升級,避免停止API導(dǎo)致用戶無法使用拴驮。
  • 有沒有在文檔里明確注明API的最低提供期限
錯誤的例子:

該API 2018-06-01下線春瞬,請注意遷移。

正確的例子:

該API將繼續(xù)維護12個月套啤,請您盡快遷移宽气。

錯誤的例子把期限說的太死了,而正確的例子則留了余地(比如再維護額外的12個月)潜沦,使用者的感受會好很多萄涯。

  • 有沒有使用HTTPS來提供API
HTTP是明文傳輸,可以被任意劫持止潮。

HTTPS采用SSL通訊窃判,保障數(shù)據(jù)安全钞楼。但是HTTPS要求客戶端嚴(yán)格驗證證書的真?zhèn)卫ⅲ駝t中間人可以偽造證書實施攻擊。

另外询件,作者強調(diào)HTTPS會導(dǎo)致請求變慢燃乍,但相比安全性仍然是值得做的。
  • 有沒有認真執(zhí)行JSON轉(zhuǎn)義
一個這樣的JSON宛琅,如果按照Content-Type: text/html被瀏覽器解析刻蟹,其中的js就會被執(zhí)行:
{"username": "<script>alert(1)</script>"}

好在大多數(shù)JSON庫默認會在編碼時會進行適當(dāng)?shù)霓D(zhuǎn)義,因此最終得不到執(zhí)行:
{"username":"<script>alert(1)<\/script>"}

所以API應(yīng)該返回完整轉(zhuǎn)義過的JSON串嘿辟,為了穩(wěn)妥也應(yīng)該設(shè)置Content-Type: application/json舆瘪,避免瀏覽器將JSON當(dāng)做html解析片效,導(dǎo)致攻擊者得以實施XSS攻擊。
  • 能不能識別X-Request-With首部英古,讓瀏覽器無法通過SCRIPT元素讀取JSON數(shù)據(jù)
假設(shè)https://api.example.com/v1/users/me是獲取當(dāng)前登錄用戶信息的接口淀衣。

攻擊者在自己的網(wǎng)站通過<script src="https://api.example.com/v1/users/me" language="vbscript"></script>可以實施攻擊。
因為接口返回的是JSON召调,而加載時指定了vb語言肯定是無法解析成功的膨桥,因此攻擊者通過設(shè)置window.onerror = function(err) {}即可被瀏覽器回調(diào)响牛,從而從錯誤信息中獲取到用戶信息搔谴。

解決這個問題的方法是禁止通過script標(biāo)簽調(diào)用API鸡挠,判定方法就是服務(wù)端判斷請求中是否有Header X-Requested-With侍筛,因為Ajax請求默認會攜帶這個header而script不會额获。
  • 通過瀏覽器訪問的API有沒有使用XSRF token
XSRF稱為跨站點請求偽造奶栖。

攻擊者在自己的網(wǎng)站做一個form表單播演,提交地址寫為目標(biāo)網(wǎng)站的表單提交地址蹬挤。當(dāng)受害者訪問攻擊者網(wǎng)站時障般,攻擊者通過javascript自動提交form表單(form.submit)环础,即可完成向目標(biāo)網(wǎng)站的提交(想象這是一個轉(zhuǎn)賬表單)。

form表單提交不受同源策略(跨域)影響剩拢,因此可以達成上述攻擊手段线得。

解決方法就是在表單里生成一次性的CSRF token放在隱藏字段中,并把token種植在用戶cookie中徐伐,在用戶提交表單到API時可以檢查表單token和cookie中的token一致贯钩,則允許提交。
  • API在接收參數(shù)時有沒有仔細檢查非法的參數(shù)(負數(shù)等)
作者以減少用戶積分的API為例办素,如果傳入一個負數(shù)積分角雷,會導(dǎo)致減法變成加法,導(dǎo)致用戶積分越來越多性穿。

所以API需要嚴(yán)格校驗參數(shù)是否合法勺三。
  • 有沒有做到即使請求重復(fù)發(fā)送,數(shù)據(jù)也不會多次更新
作者其實就是想表達冪等性需曾,舉了一個支付系統(tǒng)的例子吗坚,就不詳細描述了。
  • 有沒有在響應(yīng)消息里添加各種增強安全性的首部
有很多header是作者建議總是加在API響應(yīng)頭里的呆万,可以給瀏覽器很多建議商源,提升安全等級,就不一一描述了谋减。

比較重要的一點是set-cookie時的安全問題:
1)Secure屬性:表示cookie只能在訪問https鏈接時才能被發(fā)送給服務(wù)端牡彻,這樣可以徹底避免cookie被攻擊者在網(wǎng)絡(luò)中嗅探到。
2)HttpOnly屬性:cookie僅能供HTTP調(diào)用時使用出爹,而不允許javascript直接獲取cookie庄吼,這樣可以避免網(wǎng)站出現(xiàn)XSS漏洞的時候缎除,攻擊者通過JS代碼把用戶的會話cookie盜走。
  • 有沒有實施訪問限速
限速是為了保護API服務(wù)总寻,避免超過負載伴找。

限速一般是針對每個用戶的,限速的單位是多少分鐘內(nèi)最多訪問多少次废菱。

從實際存儲上可以采用Redis技矮,key的數(shù)量大概是"API的數(shù)量 * 用戶數(shù)量"。

API超出限速應(yīng)該返回429 Too Many Requests的http code殊轴,最好還能給出Retry-After告知多久后可以繼續(xù)使用衰倦。

  • 對預(yù)想的用例來說限速的次數(shù)有沒有設(shè)置得過少
一般來說,應(yīng)該為開放的API開發(fā)一套dashboard管理后臺旁理,從而可以靈活的為不同的用戶設(shè)置不同的限速值樊零,以及查看實時速率以及剩余調(diào)用次數(shù)等信息。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孽文,一起剝皮案震驚了整個濱河市驻襟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芋哭,老刑警劉巖沉衣,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異减牺,居然都是意外死亡豌习,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門拔疚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肥隆,“玉大人,你說我怎么就攤上這事稚失《把蓿” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵句各,是天一觀的道長吸占。 經(jīng)常有香客問我,道長诫钓,這世上最難降的妖魔是什么旬昭? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任篙螟,我火速辦了婚禮菌湃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遍略。我一直安慰自己惧所,他們只是感情好骤坐,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著下愈,像睡著了一般纽绍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上势似,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天拌夏,我揣著相機與錄音,去河邊找鬼履因。 笑死障簿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的栅迄。 我是一名探鬼主播站故,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毅舆!你這毒婦竟也來了西篓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤憋活,失蹤者是張志新(化名)和其女友劉穎岂津,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悦即,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡寸爆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了盐欺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赁豆。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖冗美,靈堂內(nèi)的尸體忽然破棺而出魔种,到底是詐尸還是另有隱情,我是刑警寧澤粉洼,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布节预,位于F島的核電站,受9級特大地震影響属韧,放射性物質(zhì)發(fā)生泄漏安拟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一宵喂、第九天 我趴在偏房一處隱蔽的房頂上張望糠赦。 院中可真熱鬧,春花似錦、人聲如沸拙泽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顾瞻。三九已至泼疑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荷荤,已是汗流浹背退渗。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蕴纳,地道東北人氓辣。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像袱蚓,于是被迫代替她去往敵國和親钞啸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348