在設(shè)計(jì)一個(gè) App 與服務(wù)端交互的 REST 風(fēng)格的 API 時(shí),一直不知道如何處理有關(guān)用戶登錄的各種問題,如: 判定用戶是否已經(jīng)登錄如何對(duì)每一次 api 請(qǐng)求進(jìn)行驗(yàn)證服務(wù)端與客戶端通信時(shí)確保用戶授權(quán)信息不被泄露。 簡(jiǎn)而言之,如何設(shè)計(jì)用戶登錄? 另:有設(shè)計(jì)過 REST API (最好是已上線的應(yīng)用)的童鞋,急切地想向您求教 My Email :Fei2037%#gmail.com My QQ:Feiox#%qq.com 實(shí)在找不到了,只能在這里求老師 ~ restfulphprest 鏈接 評(píng)論 更多
在設(shè)計(jì)一個(gè) App 與服務(wù)端交互的 REST 風(fēng)格的 API 時(shí),一直不知道如何處理有關(guān)用戶登錄的各種問題,如:
簡(jiǎn)而言之,如何設(shè)計(jì)用戶登錄?
另:有設(shè)計(jì)過 REST API (最好是已上線的應(yīng)用)的童鞋,急切地想向您求教
My Email :Fei2037%#gmail.com My QQ:Feiox#%qq.com
實(shí)在找不到了,只能在這里求老師 ~
1 個(gè)回答
API Server 如何處理 Authentication 其實(shí)和 REST 怎么設(shè)計(jì)沒什么直接關(guān)系,REST 只是一種針對(duì)基于 HTTP 的應(yīng)用(即 Web 應(yīng)用)進(jìn)行資源管理的設(shè)計(jì)原則,或者說就是指導(dǎo)你如何安排資源的一種設(shè)計(jì)理念而已。
至于處理用戶認(rèn)證(登錄等),那是在 REST 設(shè)計(jì)完了之后的事情,屬于服務(wù)器端的應(yīng)用業(yè)務(wù)邏輯。
換言之,不管你如何設(shè)計(jì)(是否 REST,或者 REST 的正不正確,徹不徹底等等),都不會(huì)影響你處理用戶認(rèn)證的業(yè)務(wù)邏輯,這根本就不是非此即彼的事情。
但是很多人搞不清楚這一點(diǎn),以為實(shí)踐了 REST(更不要說大部分實(shí)踐都是錯(cuò)的,或者不夠徹底的)就一切都和以前不同了,甚至以為一旦用了 REST,任何事情(比如身份認(rèn)證)都有且僅有一條正確的路可走了……這一點(diǎn)真有些哭笑不得。
以本問為例我們來做一個(gè)分析吧。
首先,服務(wù)器端的身份驗(yàn)證基本上有兩類方式:一是基于 Cookie 的驗(yàn)證,一是基于 Token 的驗(yàn)證。選擇哪一種要看你的實(shí)際情況?;? Cookie 的驗(yàn)證歷史悠久了,原理和做法無需贅言;近幾年涌現(xiàn)了大量的公共 API 服務(wù),它們基本上都使用了基于 Token 的驗(yàn)證,這主要是因?yàn)椋?/p>
處理跨域資源分享(CORS)——雖然 Cookie+CORS 也不是完全不可能,但是比較難搞
無狀態(tài)性——有利于服務(wù)端擴(kuò)展(伸縮性強(qiáng))
C/S 解藕——服務(wù)器端和客戶端可以完全分離,進(jìn)而靜態(tài)資源可以用 CDN 來處理,服務(wù)器端完全變成 API Service
CSRF Free——不依賴 Cookie,完全不擔(dān)心跨域偽造請(qǐng)求攻擊(這點(diǎn)尚有疑慮,有待考證)
……呃,忽然覺得有點(diǎn)跑題了,我的意思是你首先得選擇一個(gè)驗(yàn)證方式,很明顯基于 Token 的認(rèn)證是趨勢(shì)。
接下來,假定選擇了基于 Token 認(rèn)證這條路,你首先得搞明白 Token 是怎么玩的。簡(jiǎn)單地說:客戶端先發(fā)送正確的認(rèn)證信息(比如電子郵件+密碼),服務(wù)器端檢查 OK 之后生成一個(gè) token 返回給客戶端,之后客戶端所有的請(qǐng)求都要包含這個(gè) token,服務(wù)器端只需要驗(yàn)證該 token 是否有效即可。這里有一張圖,對(duì)比了 Cookie-based Authtication 和 Token-based Authentication,挺不錯(cuò)的:
好,按照 REST 的設(shè)計(jì)原則,我們需要一個(gè) Endpoint 供用戶來請(qǐng)求認(rèn)證并獲取 Token,比如像這樣:
POST /authentication在這里,“資源”就是認(rèn)證(按照 REST 的要求,用名詞來表示資源),使用
POST方法去請(qǐng)求,附帶數(shù)據(jù)為認(rèn)證用的信息,返回結(jié)果看你的業(yè)務(wù)邏輯,但至少要有一個(gè) token??蛻舳四玫?token 之后,先把它存起來(比如存到 SessionStorage 里),設(shè)置請(qǐng)求時(shí)的 HEADER 里Authorization的值為Bearer <token>,完事了。綜上所述,這事和 REST 的關(guān)系也就是設(shè)計(jì)一個(gè)獲取 Token 的 Endpoint 而已,沒啥了不起的,剩下的事情都屬于業(yè)務(wù)邏輯,該怎么寫就看你的需求了。
生成后的token不放在header,直接post過去安全嗎?
#1 蘇生不惑 · 2014年07月19日 · 回復(fù)
實(shí)際上這是 HTTP 規(guī)范的要求。
#2 nightire · 2014年07月19日 · 回復(fù)
只要通過http就有可能被截取就不安全,你可以考慮使用js在發(fā)送請(qǐng)求時(shí)在客戶端使用加密算法計(jì)算出動(dòng)態(tài)的token,不過這樣只是增加了破解的復(fù)雜程度,偽造token依然是可能的
#3 Donnie · 2014年07月19日 · 回復(fù)
用 SSL……
#4 nightire · 2014年07月20日 · 回復(fù)
有道理。。。
#5 Donnie · 2014年07月20日 · 回復(fù)
文章很詳細(xì)~ 收益了~
#6 simlegate · 2014年11月27日 · 回復(fù)
好文
#7 半卷書 · 2014年12月17日 · 回復(fù)
無意中看到這篇文章, 寫得真不錯(cuò)。 唯一一點(diǎn)不太敢茍同, “CSRF Free——不依賴 Cookie,完全不擔(dān)心跨域偽造請(qǐng)求攻擊”, 我的意思是,就算是 token, 獲取到之后也是可以偽造請(qǐng)求的阿
#8 thousand · 1月8日 · 回復(fù)
跨域是不行的吧?你可以拿到我的 token,但是我會(huì)對(duì) token 的來源加以校驗(yàn),如果是來自于信任的域也就不用擔(dān)心“偽造”了吧。當(dāng)然我不是安全領(lǐng)域的專家,答案里也是參考過去學(xué)到的資料,如有疏漏還請(qǐng)指正細(xì)節(jié)。多謝。
#9 nightire · 1月8日 · 回復(fù)
關(guān) 鍵就是你怎么能對(duì)來源加以校驗(yàn)?zāi)? 試想一下你的 app 有 10W 用戶, 分布在全國各地, 對(duì)服務(wù)器來說,每一個(gè)過來的 token 和服務(wù)器都不是一個(gè)域的. 這個(gè)沒法校驗(yàn)的. 而通常說的跨域安全問題, 是瀏覽器端的安全策略, 是為了防止諸如 XSS 跨站腳本在竊取了用戶信息之后將這些信息傳回給自己的服務(wù)器. 瀏覽器限定瀏覽某個(gè)網(wǎng)站時(shí)所加載的腳本, 后續(xù)也只能夠從同一個(gè)網(wǎng)站請(qǐng)求或提交資源 (比如通過 Ajax 等手段)
#10 thousand · 1月8日 · 回復(fù)
對(duì), 你說的是有沒錯(cuò)。我個(gè)人是這么來考慮的:用戶是通過登錄請(qǐng)求來獲得后續(xù)的訪問 token 的,那么在處理登錄請(qǐng)求的時(shí)候除了驗(yàn)證有效性之外自然也可以記錄本次登錄的來源域,那么此后附加了該 token 的請(qǐng)求自然也是同域的視為安全(服務(wù)端可以記住登錄請(qǐng)求的來源域用以后續(xù)檢查)。竊取 token 之后的訪問若是來自于不同的域,則可以視為偽造請(qǐng)求。當(dāng)然跨域安全是如你所說,主要指的是瀏覽器端的安全策略,由于我不是安全方面的專家,故此我能想到的 驗(yàn)證方式大概就是以上所述。
在實(shí)際的應(yīng)用中我和我所在的團(tuán)隊(duì)都是直接使用了第三方的驗(yàn)證組件來處理 token 的事情,比如基于 JWT 的實(shí)現(xiàn)等等。然而很抱歉的是我對(duì)這些組件的實(shí)現(xiàn)細(xì)節(jié)還沒有機(jī)會(huì)仔細(xì)去研究,也不知道是不是如我所想這樣來處理這方面的安全問題。你的回復(fù)倒是給我提了一個(gè) 醒,有必要去深究一下實(shí)現(xiàn)的細(xì)節(jié),看看在這方面有沒有漏洞吧。
至于答案處列出的那幾條,坦白說我也是摘抄自一些文章或文檔,由于都是個(gè)人筆記留下的記錄,現(xiàn)在也想不起來具體的出處。如果確認(rèn) token 對(duì)跨域偽造請(qǐng)求無能為力的話,我也會(huì)改正它。也請(qǐng)諸位知曉者提供可靠的佐證。
#11 nightire · 1月9日 · 回復(fù)
我 覺得你第一段所說的說應(yīng)該是你剛剛想出來的... 實(shí)際上 access_token/token 的設(shè)計(jì)思路不是這樣的, 它并沒有被設(shè)計(jì)成能夠記錄用戶的狀態(tài), 啊, 我們這里的主題是 RESTful API, 要知道, HTTP 是無狀態(tài)的. 你可以查一下業(yè)內(nèi)的哪些各種服務(wù)提供商它們的 api 里的 access_token 的設(shè)計(jì)思路, 包括 OAuth2 的設(shè)計(jì)思路. 不會(huì)是用 token 來記錄請(qǐng)求來源的.
而且, 就算這么做, 這種方式也是有問題的, 試想我今天在上海登錄了你的 app, 明天我去北京了, 難道我就得被強(qiáng)制下線重新登陸嗎? 當(dāng)然有很多服務(wù)會(huì)判斷出你某次不在常用登錄地點(diǎn)登錄, 會(huì)強(qiáng)制讓你重新登陸. 但那是 IP 層面安全機(jī)制, 不是 HTTP 的了.
你們團(tuán)隊(duì)使用的第三方驗(yàn)證組件應(yīng)該就是類似于 Google OpenID 或者提供 OAuth2.0 服務(wù)那種吧? 我基本可以肯定的是它們也不會(huì)把請(qǐng)求來源作為安全驗(yàn)證項(xiàng)的.
我也不是什么安全從業(yè)者, 也沒有什么全面的見解, 希望沒有誤導(dǎo)別人 :)
#12 thousand · 1月9日 · 回復(fù)
是的,那是剛才匆匆想的,因?yàn)榇饲安]有研究過安全性的問題,所以只是個(gè)人一時(shí)的思路,見笑了。
不是 OpenID 或 OAuth 1/2,而是 JWT,詳細(xì)內(nèi)容可以看這里(以及下面的討論,內(nèi)容很廣泛,信息量也挺大,我是留存準(zhǔn)備有時(shí)間去研究的)https://news./item?id=7137498
這些問題我現(xiàn)在無法準(zhǔn)確翔實(shí)的回答你,不過上面的文章和討論或許會(huì)給我們帶來新的知識(shí)和見解。我粗略的閱讀過它們,覺得還有很多底層的知識(shí)有待學(xué)習(xí) 才能搞清楚安全方面的細(xì)節(jié)。而我們所使用的第三方組件也是通過這些資源找到的。關(guān)于 JWT 的實(shí)現(xiàn) Github 上有很多,我們開始應(yīng)用的時(shí)間也不算很長,目前尚未被安全問題困擾住,所以的確沒什么研究,也沒什么發(fā)言權(quán)。
#13 nightire · 1月9日 · 回復(fù)
另 外補(bǔ)充一下,token 的設(shè)計(jì)思路自然不是我說的那樣,但是不代表具體的實(shí)現(xiàn)不能擴(kuò)展。我們開發(fā)的一款應(yīng)用就擴(kuò)展了像我所說的類似校驗(yàn)(但不是來源域,而是其他東西),這的確不 屬于廣義上 token 的設(shè)計(jì)思路,但也沒有違背它,目前來看工作也是正常的,只不過不涉及到防止偽造請(qǐng)求的安全性,所以不能算作有效的案例。
而根據(jù)我提到的文章及討論,貌似想要徹底安全也是幾乎不太可能(目前)的,又或者需要采用多種機(jī)制來協(xié)同才能達(dá)到更高的防范要求。遺憾的是我們所做的項(xiàng)目還沒有這么高的需求,有機(jī)會(huì)的話還真想親自實(shí)踐一把。
#14 nightire · 1月9日 · 回復(fù)
感謝兄臺(tái)那么晚了還回復(fù)在下... 我們的這個(gè)辯論就暫時(shí)告一段落? 我本是嵌入式工程師, 也是前不久關(guān)注了一些網(wǎng)絡(luò)安全方面的東西, 所以見解也很有限, 我最近也會(huì)再多了解一些這方面的內(nèi)容, 有新見解也會(huì)繼續(xù)在這里回復(fù)下. 望以后能繼續(xù)與兄臺(tái)交流 :)
#15 thousand · 1月9日 · 回復(fù)
@nightire
JSON Web Token這個(gè)解決方案就是你說的這個(gè)吧,感覺挺不錯(cuò)的,不知道您有試過沒?#16 天贏金創(chuàng) · 9月14日 · 回復(fù)
沒錯(cuò),JWT 就是我說的基于 Token 的認(rèn)證。我當(dāng)然用過,事實(shí)上最好用 JWT,因?yàn)樗菢?biāo)準(zhǔn),有各種語言現(xiàn)成的庫來處理。
#17 nightire · 9月14日 · 回復(fù)
好的,謝謝了,我去試試
#18 天贏金創(chuàng) · 9月14日 · 回復(fù)