程序员过关斩将--要想获取我的用户信息,就得按照规矩来
菜菜君,我又來啦
又有什么事嗎?
我按照你上篇文章寫的JWT的方式已經(jīng)把網(wǎng)站認(rèn)證寫完了,而且效果還不錯(cuò)
那恭喜你呀,下次面試又多了一項(xiàng)技能
不過,現(xiàn)在又有一個(gè)問題,我做的系統(tǒng)有一個(gè)合作商想要利用我們的用戶信息登錄他們的系統(tǒng)
你還要做授權(quán)呀?
是呀,我的思路是讓用戶在第三方系統(tǒng)的輸入賬號(hào)密碼,然后第三方的服務(wù)端請(qǐng)求我們服務(wù)器來驗(yàn)證正確性
這樣做真的好嗎?
這樣做我們的系統(tǒng)改動(dòng)很小呀,我覺得很好呀
這樣做有很多弊端呀,且聽我給你講個(gè)小故事
以下業(yè)務(wù)場(chǎng)景只針對(duì)于Web系統(tǒng),而且Web頁(yè)面有后臺(tái)服務(wù)程序的場(chǎng)景。
開端那一年,我所在公司的用戶量達(dá)到了公司成立以來的新高峰,經(jīng)過多個(gè)程序員日日夜夜加班,每個(gè)業(yè)務(wù)系統(tǒng)達(dá)到了幾乎四個(gè)9的穩(wěn)定性,同時(shí)業(yè)務(wù)在業(yè)界也有了一定的知名度。那一天突然有一個(gè)合作商登門拜訪,提出合作共贏的意向。業(yè)務(wù)的場(chǎng)景就是我們的系統(tǒng)用戶能夠在他們系統(tǒng)登錄,并能夠獲取用戶一定的信息以便進(jìn)行一些業(yè)務(wù)操作。
他們希望我們能夠把已存在的用戶數(shù)據(jù)Copy一份導(dǎo)入他們的系統(tǒng),并且新注冊(cè)的用戶進(jìn)行單項(xiàng)同步更新。這不是蝦扯蛋嗎?.....
為什么不可行為了實(shí)現(xiàn)用戶信息互通而達(dá)到業(yè)務(wù)要求,其實(shí)方案有很多。如果不是底線情況下,同步用戶信息這種方案就是一個(gè)外行人,一個(gè)扯淡的方案。為什么這么說?首先說信息同步這種方式,如果是單項(xiàng)同步,雙方所有相關(guān)人員的工作量已經(jīng)非常之大,一定條件下單項(xiàng)同步升級(jí)為雙向信息同步,雙方的編程人員將會(huì)苦不堪言。
另外撇開工作量,用戶的信息本質(zhì)上屬于用戶的私密信息,一個(gè)用戶能夠把自己的隱私放心的存儲(chǔ)在你這里,就說明了對(duì)公司的信任度。一旦發(fā)生用戶信息復(fù)制的操作,本質(zhì)上是對(duì)用戶的不負(fù)責(zé)任,道德上,法律上都有所欠缺。
解決方案作為一個(gè)技術(shù)人員,排除不合理方案,提供在業(yè)務(wù)可行情況下的技術(shù)方案是職責(zé)所在,那有沒有不用復(fù)制用戶信息這么low B的方案呢?假設(shè)我們所在公司的系統(tǒng)為A,業(yè)務(wù)的域名為www.A.com,第三方系統(tǒng)為B,業(yè)務(wù)域名為www.B.com
記住我們的最終業(yè)務(wù)目標(biāo):允許我們公司的用戶(A系統(tǒng))在第三方系統(tǒng)(B系統(tǒng))能夠登錄,并且能夠獲取用戶一些相關(guān)的信息。極限業(yè)務(wù)情況下,在A系統(tǒng)用戶修改了相關(guān)信息,并且同步到B系統(tǒng)。
解決方案1
在第三方系統(tǒng)登錄的入口,允許我方用戶輸入賬號(hào)密碼,然后第三方系統(tǒng)(客戶端或者服務(wù)端都可以)攜帶用戶輸入的賬號(hào)密碼請(qǐng)求我司登錄服務(wù)器,如果驗(yàn)證通過則返回用戶相關(guān)信息,第三方系統(tǒng)接收到返回?cái)?shù)據(jù),按照自己相關(guān)的登錄流程進(jìn)行登錄,并且可以存儲(chǔ)用戶相關(guān)的信息。請(qǐng)求的形式和大體的流程如下圖所示
http://www.A.com/login?loginname=caicai&pwd=buzhidao說實(shí)話,我并不推薦這種方案,雖然它比直接復(fù)制用戶信息要好一些,但是依然問題很大,用戶在無形中已經(jīng)把賬號(hào)密碼或者其他登錄憑證泄露給并不信任的第三方系統(tǒng)中,而這可能并非用戶想要的結(jié)果。
解決方案2
以上方案有一個(gè)致命的缺點(diǎn),那就是登錄頁(yè)面是用戶并不信任的第三方頁(yè)面,如果能避免這樣的危險(xiǎn),讓用戶在信任的我方登錄,會(huì)大大增強(qiáng)用戶的信任度。技術(shù)方面在我方實(shí)現(xiàn)登錄實(shí)在是容易,唯一需要考慮的是用戶登錄成功之后如何把用戶信息發(fā)送給第三方系統(tǒng)。如果采用請(qǐng)求調(diào)用的方式(比如:登錄成功,我方調(diào)用第三方一個(gè)接口),技術(shù)上可以實(shí)現(xiàn),但是下次再來一個(gè)第三方申請(qǐng)這樣的業(yè)務(wù),我方的調(diào)用接口可能會(huì)需要修改,所以現(xiàn)在業(yè)界比較好的也比較通用的方式是通過地址的跳轉(zhuǎn)來實(shí)現(xiàn)。具體流程如下:
1. 用戶在第三方點(diǎn)擊登錄,跳轉(zhuǎn)到我方提供的登錄頁(yè)面,頁(yè)面URL中帶有登錄成功跳轉(zhuǎn)的頁(yè)面地址,并在此頁(yè)面輸入賬號(hào)密碼。
2. 我方根據(jù)用戶賬號(hào)密碼判斷用戶正確性,登陸成功,獲取用戶信息。
3. 然后跳轉(zhuǎn)到第三方提供的登錄成功跳轉(zhuǎn)頁(yè)面,并把用戶信息攜帶過去。
4. 第三方跳轉(zhuǎn)頁(yè)面接收到用戶信息,處理剩余業(yè)務(wù),流程結(jié)束。
第一步中第三方跳轉(zhuǎn)到我方的登錄頁(yè)面URL如下所示:
http://www.A.com/login?type=userinfo&redirecturi=http://www.B.com/callback解決方案3
方案2中登錄部分已經(jīng)和方案1有了本質(zhì)的區(qū)別,雖然僅僅是一個(gè)登錄方的改變,安全性以及對(duì)用戶隱私的保護(hù)上卻有著大大的提升。但是流程中卻依然存在著主動(dòng)傳輸用戶信息,如果有人劫持的話,還是有用戶信息泄露的風(fēng)險(xiǎn)。如何避免這樣的風(fēng)險(xiǎn)呢?
試想,能否利用其它憑據(jù)來代替用戶信息呢?當(dāng)然是可以,這也是現(xiàn)代Web系統(tǒng)實(shí)現(xiàn)授權(quán)的普遍方式。用戶信息取而代之的是一個(gè)令牌,而且這個(gè)令牌有一定的時(shí)效性,只能維持一段時(shí)間內(nèi)有效,這在一定程度上保護(hù)了系統(tǒng)數(shù)據(jù)。第三方系統(tǒng)獲取到這個(gè)令牌之后,每次獲取用戶信息都會(huì)攜帶者這個(gè)令牌作為憑證,我方的系統(tǒng)同時(shí)也只認(rèn)可這個(gè)令牌作為授權(quán)的憑證。
http://www.A.com/login?type=token&redirecturi=http://www.B.com/callback這里我要順便說一下,令牌的下發(fā)是通過前端(瀏覽器)的跳轉(zhuǎn)傳輸給第三方系統(tǒng),然后第三方系統(tǒng)的前端傳輸給后端,然后第三方的后端攜帶令牌獲取用戶信息,要注意哦,如果是第三方前端頁(yè)面攜帶令牌去獲取用戶信息,毫無安全性而言。
方案4
方案3其實(shí)在很多時(shí)候已經(jīng)足夠了,但是有一點(diǎn)需要注意,每個(gè)令牌有一定的有效時(shí)間,這是設(shè)計(jì)上的優(yōu)勢(shì),同時(shí)也意味著令牌如果被其他人獲取到,一樣可以竊取用戶信息,由于在方案3中令牌的下發(fā)實(shí)際上還是通過前端(瀏覽器)來傳輸?shù)?#xff0c;凡是在前端傳輸?shù)那闆r下,就會(huì)有泄露的風(fēng)險(xiǎn),那有沒有辦法避免在前端傳輸呢?
這里需要提醒一點(diǎn),要想實(shí)現(xiàn)我方用戶可以登錄第三方系統(tǒng),并且在保護(hù)用戶隱私的情況下,在我方登錄是必須的。而且我方系統(tǒng)必須頒發(fā)給第三方系統(tǒng)一個(gè)憑證才能達(dá)到第三方獲取我方用戶的要求。
既然傳輸憑證不可避免,于是人們便想到了可以在前端(瀏覽器)傳輸一個(gè)只有一次有效的憑證,然后第三方后端依據(jù)這個(gè)憑證去獲取令牌,因?yàn)榉?wù)端的通信要比前端(瀏覽器)的通信要安全的多。于是方案4應(yīng)運(yùn)而生:
1. 用戶跳轉(zhuǎn)到我方登錄頁(yè)面進(jìn)行登錄。
2. 我方驗(yàn)證用戶用戶名密碼無誤,產(chǎn)生一個(gè)有效次數(shù)為1并且一定時(shí)間內(nèi)有效的code,并攜帶著這個(gè)code跳轉(zhuǎn)到第三方的回調(diào)頁(yè)面
3. 第三方回調(diào)頁(yè)面,收到code參數(shù),傳輸給后端程序。
4. 第三方后端程序收到code參數(shù),攜帶著code調(diào)用我方接口
5. 我方驗(yàn)證code有效性,如果有效則返回令牌信息
6. 第三方收到令牌信息,攜帶令牌信息調(diào)用我方接口獲取用戶信息
7. 我方驗(yàn)證token有效性,如果有效則返回用戶信息
8. 之后的每次調(diào)用都攜帶者token進(jìn)行訪問,code就算被人獲取到已經(jīng)不起作用
http://www.A.com/login?type=code&redirecturi=http://www.B.com/callback升級(jí)
方案4雖然看上去已經(jīng)足夠好,但是并非完美。
1.?當(dāng)?shù)谌教D(zhuǎn)到我方登錄頁(yè)面的時(shí)候,我方并不知道這個(gè)第三方是誰,是不是可信任的,所以有必要讓我方識(shí)別這個(gè)第三方是否可以信任。我方在授權(quán)第三方的時(shí)候可以給每一個(gè)第三方頒發(fā)一個(gè)類似于appid和appkey的數(shù)據(jù),appid用來標(biāo)識(shí)每一個(gè)我方授權(quán)的第三方,而且每一個(gè)appid必須注冊(cè)進(jìn)行回調(diào)的url。這樣當(dāng)?shù)谌教D(zhuǎn)到我方登錄頁(yè)面的時(shí)候,我方就可以識(shí)別出來這個(gè)第三方以及回調(diào)跳轉(zhuǎn)的url是否有效。
2. 當(dāng)?shù)谌綌y帶者code去換取token,以及之后攜帶token去獲取用戶信息的每次通信,都應(yīng)該按照我方規(guī)則利用appid和appkey進(jìn)行簽名處理,這樣我方的服務(wù)器端也能夠識(shí)別出來調(diào)用方是否是可信任的。
3. 在用戶登錄授權(quán)的頁(yè)面,用戶可勾選自己授權(quán)給第三方的數(shù)據(jù)內(nèi)容,這些權(quán)限將作用于code以及令牌中。
4. 由于每個(gè)令牌都有失效時(shí)間,如何更新令牌則會(huì)是一個(gè)技術(shù)點(diǎn),其實(shí)完全可以在下發(fā)令牌的同時(shí)也下發(fā)一個(gè)用于更新令牌的令牌,這個(gè)令牌隨著每次重新下發(fā)令牌而更新。
5. 我方用戶的信息每次更新的時(shí)候,可以把相關(guān)的令牌失效,以達(dá)到讓第三方重新獲取用戶信息而同步的效果
6. 我方登錄頁(yè)面以及供第三方調(diào)用的所有接口都應(yīng)該采用https協(xié)議,并要求所有的第三方回調(diào)頁(yè)面必須也全部采用https,這能有效的仿制惡性劫持。
不知道菜菜把不清楚author2.0 授權(quán)的同學(xué)教會(huì)了沒有,如果還不清楚,請(qǐng)私信菜菜
完
●●●●●●●●●●
總結(jié)
以上是生活随笔為你收集整理的程序员过关斩将--要想获取我的用户信息,就得按照规矩来的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 进击的.NET 在云原生时代的蜕变
- 下一篇: 从单机应用到微服务,用户认证走几步?