調(diào)用后端接口怎么樣才安全?
在APP中保存登錄數(shù)據(jù),每次調(diào)用接口時(shí)傳輸
程序員總能給自己找到偷懶的方法,有的程序?yàn)榱耸∈?,?huì)在用戶登錄后,直接把用戶名和密碼保存在本地,然后每次調(diào)用后端接口時(shí)作為參數(shù)傳遞。真省事兒??!可這種方法簡(jiǎn)單就像拿著一袋子錢在路上邊走邊喊“快來(lái)?yè)屛已剑】靵?lái)?yè)屛已?!”,一個(gè)小小的嗅探器就能把用戶的密碼拿到手,如果用戶習(xí)慣在所有地方用一個(gè)密碼,那么你闖大禍了,黑客通過(guò)撞庫(kù)的方法能把用戶的所有信息一鍋端。
登錄時(shí)請(qǐng)求一次token,之后用token調(diào)用接口
這是比較安全的方式,用戶在登錄時(shí),APP調(diào)用獲取token的接口(比如 http://api.abc.com/get_token/),用post將用戶名和密碼的摘要傳遞給服務(wù)器,然后服務(wù)器比對(duì)數(shù)據(jù)庫(kù)中的用戶信息,匹配則返回綁定該用戶的token(這一般翻譯為令牌,很直觀的名字,一看就知道是有了這玩意,就會(huì)對(duì)你放行),而數(shù)據(jù)庫(kù)中,在用戶的token表中也同時(shí)插入了這個(gè)token相關(guān)的數(shù)據(jù):這個(gè)token屬于誰(shuí)?這個(gè)token的有效期是多久?這個(gè)token當(dāng)前登錄的ip地址是?這個(gè)token對(duì)應(yīng)的deviceid是?……
這樣即便token被有心人截獲,也不會(huì)造成太大的安全風(fēng)險(xiǎn)。因?yàn)闆](méi)有用戶名和密碼,然后如果黑客通過(guò)這個(gè)token偽造用戶請(qǐng)求,我們?cè)诜?wù)器端接口被調(diào)用時(shí)就可以對(duì)發(fā)起請(qǐng)求的ip地址、user-agent之類的信息作比對(duì),以防止偽造。再然后,如果token的有效期設(shè)得小,過(guò)一會(huì)兒它就過(guò)期了,除非黑客可以持續(xù)截獲你的token,否則他只能干瞪眼。(插一句題外話:看到這里,是不是明白為什么不推薦在外面隨便接入來(lái)歷不明的wifi熱點(diǎn)了?)
tips:token如何生成? 可以根據(jù)用戶的信息及一些隨機(jī)信息(比如時(shí)間戳)再通過(guò)hash編碼(比如
md5、sha1等)生成唯一的編碼。
tips:token的安全級(jí)別,取決于你的實(shí)際需求,所以如果不是涉及財(cái)產(chǎn)安全的領(lǐng)域,并不建議太嚴(yán)格
(比如用戶走著走著,3G換了個(gè)基站,閃斷了一下IP地址變了,尼瑪token過(guò)期了,這就屬于為了不必要
的安全丟了用戶體驗(yàn),當(dāng)然如果變換的IP地址跨省的話還是應(yīng)該驗(yàn)證一下的,想想QQ有時(shí)候會(huì)讓填驗(yàn)證碼
就明白了)。
tips:接口在返回信息時(shí),可以包含本次請(qǐng)求的狀態(tài),比如成功調(diào)用,那么result['status']可能就
是'success',而反之則是'error',而如果是'error',則result['errcode']中就可以包含錯(cuò)誤
的原因,比如errcode中是'invalid_token'就可以告訴APP這個(gè)token過(guò)期或無(wú)效,這時(shí)APP應(yīng)彈出
登錄框或者用本地存儲(chǔ)的用戶名或密碼再次請(qǐng)求token(用戶選擇“記住密碼”,就應(yīng)該在本地保存用戶名
和密碼的摘要,方法見(jiàn)plus.storage的文檔)。
更安全一點(diǎn),獲取token通過(guò)SSL
剛才的方法,機(jī)智一點(diǎn)兒的讀者大概會(huì)心存疑慮:那獲取token時(shí)不還是得明文傳輸一次密碼嗎?
是的,你可以將這個(gè)獲取token的地址,用SSL來(lái)保護(hù)( 比如https://api.abc.com/get_token/ ),這樣黑客即使截了包,一時(shí)半會(huì)兒也解不出什么信息。
SSL證書(shū)的獲取渠道很多,我相信你總有辦法查到,所以不廢話了。不過(guò)話說(shuō)namecheap上的SSL證書(shū)比godaddy的要便宜得多……(這是吐槽)
tips:前段時(shí)間OpenSSL漏洞讓很多服務(wù)器遭殃,所以如果自己搭服務(wù)器,一定記得裝補(bǔ)丁。
tips:可以把所有接口都弄成SSL的嗎?可以。但會(huì)拖慢服務(wù)器,如果是配置并不自信的VPS,建議不折騰。
還要更更安全(這標(biāo)題真省事)
還記得剛才APP向服務(wù)器請(qǐng)求token時(shí),可以加入的用戶信息嗎?比如用戶的設(shè)備deviceid。
如果我們?cè)谡{(diào)用接口時(shí),還附帶一個(gè)當(dāng)前時(shí)間戳參數(shù)timestamp,同時(shí),用deviceid和這個(gè)時(shí)間戳再生成一個(gè)參數(shù)sign,比如 md5(deviceid timestamp token)這樣的形式。而服務(wù)端首先驗(yàn)證一下參數(shù)中的時(shí)間戳與當(dāng)前服務(wù)器時(shí)間是否一致(誤差保持在合理范圍內(nèi)即可,比如5分鐘),然后根據(jù)用戶保存在服務(wù)器中的deviceid來(lái)對(duì)參數(shù)中的時(shí)間戳進(jìn)行相同的變形,驗(yàn)證是否匹配,那便自然“更更安全”了。
tips:如果對(duì)整個(gè)調(diào)用請(qǐng)求中的參數(shù)進(jìn)行排序,再以deviceid和timestamp加上排序后的參數(shù)來(lái)對(duì)整個(gè)調(diào)用生成1個(gè)sign,黑客即使截獲sign,不同的時(shí)間點(diǎn)、參數(shù)請(qǐng)求所使用的sign也是不同的,難以偽造,自然會(huì)更安全。當(dāng)然,寫(xiě)起來(lái)也更費(fèi)事。
tips:明白了原理,整個(gè)驗(yàn)證過(guò)程是可以根據(jù)自己的需求改造的。