APP后端開發(fā)之請(qǐng)求雜談

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種方式:

  1. 寫進(jìn)文件
  2. 寫進(jìn)MySql數(shù)據(jù)庫
  3. 寫進(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)包含至少以下幾類信息:

  1. 發(fā)生錯(cuò)誤的接口地址和時(shí)間
  2. 該請(qǐng)求的header頭中的access_token,其實(shí)更合理地應(yīng)該通過access_token獲取用戶id并記錄起意,因?yàn)閍ccess_token是有可能更改的。
  3. 該請(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ò)誤排查逗爹。
  4. 該請(qǐng)求產(chǎn)生錯(cuò)誤信息。
  5. 該請(qǐng)求的http狀態(tài)碼嚎于。
  6. 業(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的好處在于:

  1. 我們可以自定義更多的狀態(tài)碼和錯(cuò)誤信息。一般我會(huì)做一個(gè)接口錯(cuò)誤地圖類,然后根據(jù)code的值獲取對(duì)應(yīng)的message遭垛。
  2. 更好地對(duì)code進(jìn)行分類定義尼桶,比如1000 開頭的表示 a 控制器各個(gè)接口的產(chǎn)生的各種錯(cuò)誤
    2000 開頭的表示 b控制器各個(gè)接口產(chǎn)生的各種錯(cuò)誤。
    -1 表示 錯(cuò)誤地圖類中 未定義的錯(cuò)誤锯仪。
  3. 業(yè)務(wù)層的狀態(tài)碼不和通訊層狀態(tài)碼耦合泵督,更詳細(xì)地展示業(yè)務(wù)層錯(cuò)誤信息。
  4. 避免客戶端出現(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)證,所以:

  1. 如果你允許同時(shí)登陸多臺(tái)設(shè)備匾灶,你只需要登陸后復(fù)用user表中的access_token棱烂。

  2. 如果那你不允許同時(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ì)做哪些呢?

  1. cookie在生成時(shí)就會(huì)被指定一個(gè)Expire值驾孔,這就是cookie的生存周期芍秆,在這個(gè)周期內(nèi)cookie有效,超出周期cookie就會(huì)被清除
  2. 對(duì)cookie進(jìn)行加密翠勉,嵌入時(shí)間戳保證每次加密后的密文不同
  3. 不允許跨域使用

所以妖啥,雖然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端異常:

  1. crash 使用APP過程中突然出現(xiàn)閃退
  2. 卡頓 出現(xiàn)畫面卡頓
  3. Exception 程序被catch起來的Exception
  4. 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) :

  1. 聽云
  2. OneAPM

消息推送

  • 原生方式
  1. 客戶端輪詢 不推薦
  2. 服務(wù)端主動(dòng)推客戶端 實(shí)現(xiàn)難度大
  • 第三方推送服務(wù)
  1. 極光推送
    推薦使用restful api接口 比其他SDK用起來更方便
  2. 百度云推送
  3. 信鴿

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),自定義更方便存捺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末槐沼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子召噩,更是在濱河造成了極大的恐慌母赵,老刑警劉巖逸爵,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件具滴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡师倔,警方通過查閱死者的電腦和手機(jī)构韵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疲恢,你說我怎么就攤上這事凶朗。” “怎么了显拳?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵棚愤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我杂数,道長(zhǎng)宛畦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任揍移,我火速辦了婚禮次和,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘那伐。我一直安慰自己踏施,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布罕邀。 她就那樣靜靜地躺著畅形,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诉探。 梳的紋絲不亂的頭發(fā)上束亏,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音阵具,去河邊找鬼碍遍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛阳液,可吹牛的內(nèi)容都是我干的怕敬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼帘皿,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼东跪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鹰溜,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤虽填,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后曹动,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體斋日,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年墓陈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恶守。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片第献。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖兔港,靈堂內(nèi)的尸體忽然破棺而出庸毫,到底是詐尸還是另有隱情,我是刑警寧澤衫樊,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布飒赃,位于F島的核電站,受9級(jí)特大地震影響科侈,放射性物質(zhì)發(fā)生泄漏盒揉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一兑徘、第九天 我趴在偏房一處隱蔽的房頂上張望刚盈。 院中可真熱鬧,春花似錦挂脑、人聲如沸藕漱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娩践。三九已至肤无,卻和暖如春梗逮,著一層夾襖步出監(jiān)牢的瞬間散劫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工牍戚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侮繁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓如孝,卻偏偏與公主長(zhǎng)得像宪哩,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子第晰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容