Header頭
header 頭推薦加上字段:
- Authorization
用來存放access_token,通過該token對(duì)用戶進(jìn)行認(rèn)證称杨》踩溃可以理解其作用等同于cookie中的session_id,有該令牌就默認(rèn)用戶已經(jīng)認(rèn)證登陸過。
- Signture 客戶端簽名
用來判斷該請(qǐng)求是否是客戶端APP發(fā)起的請(qǐng)求,現(xiàn)在最常見的兩種方法 一種 是通過ASE加密解密來實(shí)現(xiàn)囱修。一種是通過比對(duì)信息摘要的方式款熬。
最簡(jiǎn)單的生成方式是給出一個(gè)隨機(jī)值和時(shí)間戳挣柬,還有和服務(wù)端約定好的鹽值按照一定的順序進(jìn)行MD5加密钥顽。
signture = md5(nonce + timastamp + salt)
服務(wù)端收到該簽名的時(shí)候,按照約定的順序進(jìn)行MD5加密比對(duì)簽名舞箍,如果服務(wù)端生成的簽名與客戶端簽名不一致舰褪,則可認(rèn)為不是客戶端發(fā)起的請(qǐng)求,此時(shí)不響應(yīng)該請(qǐng)求疏橄。當(dāng)然使用這種方法要同時(shí)提交timestamp 和 隨機(jī)字符串nonce占拍。
- version 客戶端版本
用來存放客戶端版本號(hào),主要是小版本捎迫,大版本的話一般服務(wù)端會(huì)開新接口晃酒。但是比較好的做法,是客戶端每一次發(fā)布都要有一個(gè)版本號(hào)窄绒。就算是此次發(fā)布贝次,服務(wù)端沒做任何更改,只要客戶端新發(fā)布也應(yīng)該給一個(gè)新的版本號(hào)彰导。然后將這個(gè)版本號(hào)寫入header 頭中蛔翅。這樣的好處是如果請(qǐng)求出現(xiàn)錯(cuò)誤敲茄,我們能夠定位到是哪個(gè)版本的APP出現(xiàn)了該錯(cuò)誤,可以更容易的定位復(fù)現(xiàn)錯(cuò)誤山析。更詳細(xì)地還可以把設(shè)備的操作系統(tǒng)和型號(hào)也在header頭提交堰燎。
- timestamp 請(qǐng)求時(shí)間戳
客戶端發(fā)送請(qǐng)求時(shí)的時(shí)間戳,可用于請(qǐng)求過期判斷笋轨。
客戶端簽名細(xì)節(jié)
- 防止重放攻擊
雖然signture的存在秆剪,使我們可以判斷該請(qǐng)求是否是客戶端生成,從而只響應(yīng)客戶端的請(qǐng)求爵政。但是這樣安全性還是不夠鸟款。
一個(gè)典型的攻擊手法時(shí),通過抓包客戶端生成的簽名不斷地進(jìn)行接口請(qǐng)求茂卦。最常見的就是利用該簽名不停地請(qǐng)求短信驗(yàn)證碼接口,直到服務(wù)器的驗(yàn)證碼余額耗光组哩。
防止重放攻擊的最有效方式就是保持signture的唯一性等龙。客戶端必須生成唯一的signture伶贰,同時(shí)服務(wù)端也要保證對(duì)于一個(gè)signture只響應(yīng)一次請(qǐng)求蛛砰。
- 保證客戶端簽名的唯一性
客戶端保證每次生成一個(gè)唯一地signture的最簡(jiǎn)單方式是在生成簽名的方法中加入時(shí)間戳。
服務(wù)端保證對(duì)每一個(gè)signture簽名黍衙,只使用一次的實(shí)現(xiàn)方法是:對(duì)每次請(qǐng)求做判斷泥畅,如果該請(qǐng)求攜帶的簽名沒有使用過,則響應(yīng)該請(qǐng)求琅翻,并把該簽名記錄在服務(wù)端并標(biāo)記為已使用位仁。如果查到該請(qǐng)求攜帶的簽名已經(jīng)被標(biāo)記為已使用,則不響應(yīng)該請(qǐng)求方椎。
服務(wù)端對(duì)signture做記錄聂抢,一般通過3種方式:
- 寫進(jìn)文件
- 寫進(jìn)MySql數(shù)據(jù)庫
- 寫進(jìn)Redis
寫進(jìn)文件的弊端,在于無法供分布式系統(tǒng)使用棠众。MySql的弊端在于請(qǐng)求數(shù)多時(shí)增加了數(shù)據(jù)庫的壓力琳疏。所以最好的方式還是寫進(jìn)Redis里。
- 增加簽名超時(shí)機(jī)制
我們保證了客戶端簽名唯一性的方法是將每次請(qǐng)求的signtue記錄在服務(wù)端闸拿。但是隨著請(qǐng)求的增加空盼,記錄的signture也越來越多。每次請(qǐng)求都要逐一比對(duì)以前所有請(qǐng)求記錄下的signture新荤,這樣顯然是不合理揽趾。
所以我們正確的方式,不應(yīng)該是單純把signture寫進(jìn)文件苛骨,mysql但骨,或redis励七。而應(yīng)該是做一個(gè)文件緩存,或是寫數(shù)據(jù)庫臨時(shí)表奔缠,或是redis緩存掠抬。
但是如果我們只比對(duì)緩存期內(nèi)的signture,攻擊者還是可以通過使用已到期被緩存清除的signture來進(jìn)行重放攻擊校哎。于是我們引入了一個(gè)超時(shí)機(jī)制两波,如果該請(qǐng)求攜帶的timestamp 比當(dāng)前的服務(wù)端時(shí)間相隔已經(jīng) 大于singture緩存時(shí)間,則不響應(yīng)這個(gè)請(qǐng)求闷哆。這樣就保證了腰奋,攻擊者無法使用被緩存清除的signture進(jìn)行重放攻擊。
當(dāng)然超時(shí)時(shí)間也不能設(shè)置太小抱怔,因?yàn)榭蛻舳苏?qǐng)求到達(dá)服務(wù)端需要一定的時(shí)間劣坊。所以超時(shí)時(shí)間的設(shè)置應(yīng)滿足
(服務(wù)端當(dāng)前時(shí)間 - 客戶端提交的timestamp) < 超時(shí)時(shí)間 < signture緩存到期時(shí)間
引入超時(shí)機(jī)制的另一個(gè)好處是防止了一部分的中間人攻擊。因?yàn)榻俪衷黾恿苏?qǐng)求的時(shí)間屈留,因?yàn)槌瑫r(shí)機(jī)制的存在局冰,可能使被劫持的請(qǐng)求失效。
- 防止超時(shí)時(shí)間下溢攻擊
引入了超時(shí)機(jī)制以后灌危,可能我們一般都會(huì)這樣寫
if( (服務(wù)端當(dāng)前時(shí)間 - 客戶端提交的timestamp) < 超時(shí)時(shí)間 ){
超時(shí)了;
}
但是如果攻擊者 更改了客戶端時(shí)間康二,使客戶端提交的timestamp是一個(gè)比服務(wù)端時(shí)間還超前幾天或是幾年的時(shí)間戳,并生成了一個(gè)對(duì)應(yīng)的signture勇蝙。這個(gè)時(shí)候沫勿,當(dāng)該請(qǐng)求響應(yīng)后。攻擊者等待一段時(shí)間味混,等緩存中這個(gè)signture 失效了产雹,攻擊者就可以拿著這個(gè)signture和timestamp 進(jìn)行重放攻擊了,因?yàn)檫@個(gè)timestamp 超前了服務(wù)端時(shí)間幾天或幾年翁锡,所以
服務(wù)端 - 客戶端提交的timestamp = 負(fù)數(shù) < 超時(shí)時(shí)間
所以洽故,通過負(fù)數(shù)小于超時(shí)時(shí)間,繞過了超時(shí)機(jī)制盗誊,使signture又可以重新使用时甚。當(dāng)然這種情況下的重放攻擊已經(jīng)很弱了,因?yàn)閟ignture使用過一次就會(huì)被緩存哈踱,所以通過下溢重新使用signture也要等到上一次signture的緩存失效了荒适。則兩次攻擊之間,便必須隔一段緩存有效期开镣。
所以刀诬,更合理的話,除了比對(duì)請(qǐng)求時(shí)間是否小于超時(shí)時(shí)間邪财。還應(yīng)該判斷:
服務(wù)端時(shí)間 - 客戶端提交的timestamp > 0
- 保證客戶端服務(wù)端的時(shí)間一致性
引入超時(shí)機(jī)制的前提是客戶端和服務(wù)端的時(shí)間誤差在可接受的范圍陕壹。
試想一下质欲,如果客戶端請(qǐng)求需要0.5s到達(dá)服務(wù)端,所以服務(wù)端的超時(shí)時(shí)間設(shè)置了1s糠馆。但是客戶端的時(shí)間比服務(wù)端慢了2s 嘶伟。這個(gè)時(shí)候當(dāng)客戶端的timestamp 提交到服務(wù)端時(shí)
本來應(yīng)該是
服務(wù)端當(dāng)前時(shí)間-客戶端提交的timestamp = 0.5 < 1 // 不超時(shí)
結(jié)果因?yàn)榭蛻舳藭r(shí)間比服務(wù)端時(shí)間慢了2s,使timestamp 到達(dá)服務(wù)端時(shí),變成了
服務(wù)端當(dāng)前時(shí)間-客戶端提交的timestamp = 2.5s > 1 // 超時(shí)
所以客戶端服務(wù)端時(shí)間不一致的會(huì)造成客戶端所有請(qǐng)求都因?yàn)槌瑫r(shí)而無法響應(yīng)又碌。
那么如何保證服務(wù)端和客戶端的時(shí)間一致性呢九昧?
一個(gè)最常用的解決方式就是:
服務(wù)端給出一個(gè)接口返回當(dāng)前時(shí)間戳,
客戶端請(qǐng)求該接口獲取時(shí)間戳毕匀,加上該請(qǐng)求的響應(yīng)時(shí)間與當(dāng)前時(shí)間戳相減得出時(shí)間差铸鹰。
而客戶端提交的timestamp 就是當(dāng)前時(shí)間戳加上服務(wù)端與客戶端的時(shí)間差。
客戶端簽名生成方式
加密 還是 信息摘要 ?
- 信息摘要
信息摘要的好處在于服務(wù)端處理更簡(jiǎn)單皂岔,只需要生成對(duì)應(yīng)的簽名進(jìn)行比對(duì)即可蹋笼。
- 加密
加密的方式生成簽名常見的可以采用ASE加密,借鑒微信支付寶sdk簽名的生成方式躁垛,把header頭的重要的參數(shù)剖毯,都參與signture的生成。這樣的好處在于更加安全缤苫,如果傳輸中header頭的參數(shù)被劫持更改,會(huì)造成服務(wù)端驗(yàn)簽失敗墅拭,則請(qǐng)求自然就不響應(yīng)了活玲。
Timestamp
timestamp 是要提交10位還是13位的時(shí)間戳呢?
這個(gè)問題最常見于用PHP寫的APP后端谍婉。因?yàn)镻HP中使用的時(shí)間戳是10位的舒憾,time()
也是只返回一個(gè)10位的時(shí)間戳。
但是穗熬,我還是認(rèn)為應(yīng)該使用一個(gè)13位的時(shí)間戳镀迂。至少你生成signture的時(shí)候應(yīng)使用13位的時(shí)間戳,因?yàn)檫@樣實(shí)時(shí)性更強(qiáng)唤蔗,防止客戶端太多的時(shí)候探遵,不同的客戶端同時(shí)生成簽名時(shí),出現(xiàn)signture相同的情況妓柜。
所以箱季,反正客戶端使用的是13位的時(shí)間戳,如果提交一個(gè)10位的時(shí)間戳棍掐,它也要進(jìn)行截取藏雏。不如直接提交過來怎么使用,服務(wù)端自己決定的作煌。
<?php
// 13 位時(shí)間戳轉(zhuǎn)10位 進(jìn)行比對(duì)
time() - ceil($timestamp/1000);
// 如果是生成13位時(shí)間戳進(jìn)行比對(duì)
list($micro,$time) = expload(' ',microtime());
ceil(($time + $micro)*1000) - $timestamp;
// 更新 其實(shí)microtime()是可以直接返回一個(gè)float數(shù)據(jù)掘殴,只需要傳一個(gè)常數(shù)true
ceil(microtime(true)*1000) - $timestamp
請(qǐng)求錯(cuò)誤日志
APP開發(fā)的其中一個(gè)難點(diǎn)就是錯(cuò)誤定位難赚瘦,復(fù)現(xiàn)難。所以寫日志就非常重要了奏寨。
當(dāng)前錯(cuò)誤日志所需記錄的信息應(yīng)包含至少以下幾類信息:
- 發(fā)生錯(cuò)誤的接口地址和時(shí)間
- 該請(qǐng)求的header頭中的access_token,其實(shí)更合理地應(yīng)該通過access_token獲取用戶id并記錄起意,因?yàn)閍ccess_token是有可能更改的。
- 該請(qǐng)求的客戶端版本號(hào)服爷,更詳細(xì)的話杜恰,還有操作系統(tǒng)和設(shè)備型號(hào)。這就是為什么前面提倡將這幾個(gè)參數(shù)寫在header頭里每次請(qǐng)求都提交的原因仍源⌒暮郑客戶端版本號(hào)可以用來判斷哪個(gè)版本請(qǐng)求會(huì)出現(xiàn)錯(cuò)誤,然后再?zèng)Q定如何更改笼踩。操作系統(tǒng)和設(shè)備型號(hào)主要用于給前端兼容性錯(cuò)誤排查逗爹。
- 該請(qǐng)求產(chǎn)生錯(cuò)誤信息。
- 該請(qǐng)求的http狀態(tài)碼嚎于。
- 業(yè)務(wù)層如果有錯(cuò)誤狀態(tài)碼也需要記錄
請(qǐng)求返回格式
APP開發(fā)現(xiàn)在比較流行的還是返回json格式而不是xml格式掘而。
返回json格式的數(shù)據(jù)一般是這樣的:
{
"status" :200,
"message":"ok",
"data" :{},
}
status 返回請(qǐng)求狀態(tài)碼,一般復(fù)用http狀態(tài)碼于购。
message 返回請(qǐng)求消息袍睡,如果有錯(cuò)誤這里寫錯(cuò)誤信息。
data 是返回的數(shù)據(jù)
但是我還是比較喜歡以下這種返回方式
{
"code":0
"data":{}
}
// 為什么請(qǐng)求成功 要使用0作為code狀態(tài)碼呢肋僧,0的第一感覺不是false嗎斑胜?
嗯,錯(cuò)誤情況千千萬嫌吠,而成功只有一種情況止潘。正數(shù)負(fù)數(shù)千千萬,而0也只有一個(gè)辫诅。
{
"code":1001
"message":"某個(gè)控制器請(qǐng)求出錯(cuò)"
}
為什么呢凭戴?
因?yàn)椴幌胗胔ttp status來傳達(dá)API請(qǐng)求狀態(tài),http status 傳達(dá)的是通訊層的狀態(tài)炕矮。API是為了滿足業(yè)務(wù)么夫,返回的數(shù)據(jù)應(yīng)包含業(yè)務(wù)層的狀態(tài)碼。業(yè)務(wù)層不和通訊層耦合肤视,不拿http status 取巧魏割。
當(dāng)然對(duì)于這點(diǎn),喜歡使用http status 的同學(xué)也有不同的看法钢颂,這就看個(gè)人的喜好了钞它。
我覺得使用code的好處在于:
- 我們可以自定義更多的狀態(tài)碼和錯(cuò)誤信息。一般我會(huì)做一個(gè)接口錯(cuò)誤地圖類,然后根據(jù)code的值獲取對(duì)應(yīng)的message遭垛。
- 更好地對(duì)code進(jìn)行分類定義尼桶,比如1000 開頭的表示 a 控制器各個(gè)接口的產(chǎn)生的各種錯(cuò)誤
2000 開頭的表示 b控制器各個(gè)接口產(chǎn)生的各種錯(cuò)誤。
-1 表示 錯(cuò)誤地圖類中 未定義的錯(cuò)誤锯仪。 - 業(yè)務(wù)層的狀態(tài)碼不和通訊層狀態(tài)碼耦合泵督,更詳細(xì)地展示業(yè)務(wù)層錯(cuò)誤信息。
- 避免客戶端出現(xiàn)某個(gè)接口返回未考慮進(jìn)去的非200 ok的http 狀態(tài)碼庶喜,而造成客戶端卡死的情況小腊。我喜歡在后端對(duì)http響應(yīng)的狀態(tài)碼進(jìn)行判斷,如果該請(qǐng)求的響應(yīng)碼不是200 就把查看錯(cuò)誤地圖類轉(zhuǎn)化為對(duì)應(yīng)的code狀態(tài)碼和錯(cuò)誤message,寫入日志久窟,并把http 狀態(tài)碼改回200秩冈。這樣保證每次http請(qǐng)求基本都會(huì)返回200,可預(yù)知的錯(cuò)誤都轉(zhuǎn)化為返回的json數(shù)據(jù)中的code狀態(tài)碼。
Authorization
- App后端開發(fā)不能使用session斥扛?
雖然app通過接口請(qǐng)求的方式與后端交互入问,沒有cookie,但是依然可以使用session。session的實(shí)現(xiàn)不依賴于cookie,如果你把cookie中的session_id 但是打開session的令牌稀颁。那么header頭中的Authorization 字段提交的access_token 同樣可以看成令牌實(shí)現(xiàn)同樣的作用芬失。
- 是否允許賬戶同時(shí)在兩個(gè)以上的設(shè)備登陸
因?yàn)槲覀兺ㄟ^Authorization來獲取認(rèn)證,所以:
如果你允許同時(shí)登陸多臺(tái)設(shè)備匾灶,你只需要登陸后復(fù)用user表中的access_token棱烂。
如果那你不允許同時(shí)登陸多臺(tái)設(shè)備,則可以選擇登陸時(shí)刷新access_token阶女,這樣就使得其他在線的設(shè)備請(qǐng)求頭中的Authorization字段提交的access_token與user表中的不匹配颊糜,自然就被擠下線了。
- access_token的安全性問題
我們通過access_token來獲取用戶张肾,也就意味著access_token如果被劫持就等同于用戶的賬戶被盜芭析。
你想想同樣作為獲取服務(wù)端session的令牌锚扎,使用cookie時(shí)吞瞪,為了安全我們一般會(huì)做哪些呢?
- cookie在生成時(shí)就會(huì)被指定一個(gè)Expire值驾孔,這就是cookie的生存周期芍秆,在這個(gè)周期內(nèi)cookie有效,超出周期cookie就會(huì)被清除
- 對(duì)cookie進(jìn)行加密翠勉,嵌入時(shí)間戳保證每次加密后的密文不同
- 不允許跨域使用
所以妖啥,雖然signture的唯一性已經(jīng)為我們證明了是APP發(fā)起的合法請(qǐng)求,但是嚴(yán)格來說我們也不能單單對(duì)access_token 進(jìn)行明文傳輸对碌。
我們可以考慮在Authorization 字段不是簡(jiǎn)單地傳輸access_token的值荆虱,可以傳一個(gè)access_token和時(shí)間戳的加密字符串,在服務(wù)端再進(jìn)行解密,并先判斷是否超時(shí)怀读。如果要安全性高些诉位,還可以參考signture做唯一性處理。
版本升級(jí)
建議建一個(gè)版本升級(jí)表用來存放版本升級(jí)信息菜枷。并且要有是否強(qiáng)制更新字段苍糠。
我們header頭提交version參數(shù),寫日志為的都是不想失去對(duì)客戶端的控制啤誊,能更好的定位錯(cuò)誤岳瞭。但是app與傳統(tǒng)的web開發(fā)的一個(gè)區(qū)別,就是web開發(fā)頁面做了修改蚊锹,所有的用戶都能看到修改瞳筏,但是APP的話,只要用戶沒有更新枫耳,已修復(fù)的bug,對(duì)用戶而言 依舊存在乏矾。
版本升級(jí)表設(shè)計(jì)
字段名 | 類型 | 備注 |
---|---|---|
id | int | 主鍵id |
app_type | varchar | 客戶端版本類型 ios or android |
version | int | 開發(fā)版本號(hào) |
version_code | varchar | 客戶端版本號(hào)(1.0.2) |
upagrade_desc | varchar | 更新提示語 |
apk_url | varchar | 更新包鏈接 |
is_force | tinyint | 是否強(qiáng)制更新 |
created_at | int | 創(chuàng)建時(shí)間 |
status | tinyint | 是否已發(fā)布 |
有了版本升級(jí)表以后,我們就能更方便直觀地管理查看我們發(fā)布的版本迁杨。
而且我們可以在打開APP時(shí)請(qǐng)求接口钻心,查詢版本設(shè)計(jì)表獲得最新的版本與header頭提交的version字段作對(duì)比,判斷是否需要更新铅协,彈出更新窗口捷沸。
對(duì)于需要強(qiáng)制更新的版本,彈窗應(yīng)設(shè)置為不允許用戶點(diǎn)擊取消狐史,一定要更新才能使用該APP痒给。這樣我們就可以把一些重大更新或者修復(fù)一些重要bug的版本設(shè)為強(qiáng)制更新,不更新就不讓繼續(xù)使用骏全。
用戶分析
為了更好地進(jìn)行用戶分析苍柏,我們還可以建一個(gè)APP登陸記錄表。
打開APP時(shí)就通過header把用戶信息記錄起來姜贡,用來做用戶分析试吁。用戶日活量,月活量楼咳。
客戶端一打開就將數(shù)據(jù)發(fā)給該接口就行熄捍,不管請(qǐng)求是否成功,客戶端都不需要關(guān)心母怜。
字段名 | 類型 | 備注 |
---|---|---|
id | int | 主鍵id |
app_type | varchar | 客戶端版本類型 ios or android |
version | int | 開發(fā)版本號(hào) |
version_code | varchar | 客戶端版本號(hào)(1.0.2) |
model | varchar | 設(shè)備型號(hào) 小米 蘋果 |
uid | int | 用戶id |
created_at | int | 創(chuàng)建時(shí)間 |
app_active_log 表
字段名 | 類型 | 備注 |
---|---|---|
id | int | 主鍵id |
app_type | varchar | 客戶端版本類型 ios or android |
version | int | 開發(fā)版本號(hào) |
version_code | varchar | 客戶端版本號(hào)(1.0.2) |
model | varchar | 設(shè)備型號(hào) 小米 蘋果 |
uid | int | 用戶id |
created_at | int | 創(chuàng)建時(shí)間 |
這個(gè)表的另一個(gè)功能還可以統(tǒng)計(jì)某個(gè)版本的用戶量或是Android還是IOS用戶多余耽,方便我們更新版本時(shí)選擇先開發(fā)IOS版或是安卓版,或者出現(xiàn)bug決定哪個(gè)版本先修復(fù)苹熏。
客戶端異常監(jiān)控碟贾,分析
常見的APP端異常:
- crash 使用APP過程中突然出現(xiàn)閃退
- 卡頓 出現(xiàn)畫面卡頓
- Exception 程序被catch起來的Exception
- ANR 出現(xiàn)提示無響應(yīng)彈框(Android)
我們?cè)诜?wù)端寫日志币喧,在header頭提交設(shè)備信息這些都是為了更好地定位客戶端的錯(cuò)誤。但是我們的日志只能記錄接口調(diào)用異常袱耽。對(duì)于客戶端的異常卻無能為力粱锐。
為此,我們應(yīng)該和客戶端配合扛邑。把客戶端產(chǎn)生異常定期上報(bào)到服務(wù)端怜浅。方便客戶端工程師定位復(fù)現(xiàn)并修復(fù)客戶端異常
我們可以建一個(gè) app_crap 表來統(tǒng)計(jì)收集 crash 卡頓 Exception ANR的次數(shù)和影響用戶量 用戶數(shù)
字段名 | 類型 | 備注 |
---|---|---|
id | int | 主鍵id |
app_type | varchar | 客戶端版本類型 ios or android |
version | int | 開發(fā)版本號(hào) |
version_code | varchar | 客戶端版本號(hào)(1.0.2) |
model | varchar | 設(shè)備型號(hào) 小米 蘋果 |
type | tinyint | 端異常類型 卡頓 閃退 |
description | varchar | 描述 |
created_at | int | 創(chuàng)建時(shí)間 |
當(dāng)然,客戶端記錄這些數(shù)據(jù)比較麻煩.一個(gè)更好的解決方案是在客戶端中集成第三方服務(wù)提供的SDK蔬崩,將這些數(shù)據(jù)提交到第三方平臺(tái)恶座,客戶端工程師可以登錄第三方平臺(tái)查看客戶端異常統(tǒng)計(jì)。
常用的第三方平臺(tái) :
消息推送
- 原生方式
- 客戶端輪詢 不推薦
- 服務(wù)端主動(dòng)推客戶端 實(shí)現(xiàn)難度大
- 第三方推送服務(wù)
-
極光推送
推薦使用restful api接口 比其他SDK用起來更方便 - 百度云推送
- 信鴿
APP后端開發(fā)工具推薦
接口調(diào)試神器
內(nèi)網(wǎng)映射工具沥阳。app開發(fā)一個(gè)麻煩的地方在于無法本地調(diào)試跨琳,因?yàn)榭蛻舳诵枰?qǐng)求有域名或公網(wǎng)ip的服務(wù)端代碼,雖然公司有測(cè)試服務(wù)器桐罕,但是有些時(shí)候測(cè)試服上有很多人同時(shí)使用脉让,我git提交了修改后的服務(wù)端代碼不能馬上reset hard生效」ε冢或者測(cè)試服不在我開發(fā)的分支溅潜。ngrok的好處是內(nèi)網(wǎng)映射,給你的電腦綁定一個(gè)域名薪伏。而客戶端測(cè)試時(shí)填寫這個(gè)域名能訪問到你電腦的服務(wù)端代碼滚澜,實(shí)時(shí)調(diào)試更方便。
php一個(gè)http 請(qǐng)求包嫁怀,通過composer 安裝快速使用设捐,可用來寫接口的測(cè)試代碼,模擬發(fā)起http請(qǐng)求塘淑,比起postman的優(yōu)點(diǎn)在于萝招,通過代碼實(shí)現(xiàn),自定義更方便存捺。