只要是需要登錄的系統(tǒng)盆犁,就必然涉及到“身份驗(yàn)證”,那么篡九,前端是如何配合后臺(tái)做身份驗(yàn)證呢谐岁?
一般由兩種模式,Cookies和Tokens榛臼。前者是傳統(tǒng)模式伊佃,后者乃新起之秀。先看一張對(duì)比圖沛善,大致了解二者差異:
共同點(diǎn)
- 都是利用HTTP request header來(lái)傳遞身份信息
- 都需要后臺(tái)給予驗(yàn)證身份的唯一ID(也可理解為唯一的驗(yàn)證信息)
下面分別分析這兩種模式航揉。
Cookies
Cookies驗(yàn)證是有狀態(tài)(stateful)的。這意味著金刁,權(quán)限信息(比如session ID)必須同時(shí)在客戶端和服務(wù)端維護(hù)迷捧。服務(wù)端需要根據(jù)session cookies信息去數(shù)據(jù)庫(kù)查詢用戶相關(guān)信息织咧;客戶端每次發(fā)起請(qǐng)求時(shí)都必須帶上Cookies信息作為身份驗(yàn)證。
Cookies有如下特征:
- 不需要前端存儲(chǔ)
Cookies由后臺(tái)設(shè)置(response header里的Set-Cookie
)漠秋,瀏覽器會(huì)在后續(xù)的請(qǐng)求中自動(dòng)加上Cookies信息笙蒙。 - 有CSRF(跨站點(diǎn)偽造請(qǐng)求)風(fēng)險(xiǎn)
Cookies是不支持跨域訪問(wèn)的,一般只能在某個(gè)域名及其子域名下被訪問(wèn)庆锦。但是捅位,由于Cookies可以通過(guò)JS代碼獲取(document.cookies
)搂抒,由此艇搀,可能會(huì)引發(fā)安全問(wèn)題,比如著名的CSRF攻擊(跨站請(qǐng)求偽造)求晶。 - 移動(dòng)端用在使用cookie時(shí)有各種不便利和局限
移動(dòng)端平臺(tái)和Cookies配合并不是太好焰雕,可能會(huì)在Cookies使用上有局限性。 - Cookies可以在同一域名下或者同一主域不同子域下共享芳杏,一旦跨主域矩屁,就無(wú)法共享
如果遇到跨域共享身份信息的情況,就必須靠服務(wù)器協(xié)助(例如單點(diǎn)登錄:一個(gè)身份爵赵,需要登錄多個(gè)主域)
小貼士
API跨域請(qǐng)求時(shí)吝秕,如果請(qǐng)求方式為JSONP,那么空幻,瀏覽器會(huì)自動(dòng)在request請(qǐng)求中帶上Cookies烁峭。
* JSONP利用script標(biāo)簽實(shí)現(xiàn)跨越,而script標(biāo)簽的src屬性發(fā)起的請(qǐng)求類似資源文件請(qǐng)求秕铛;
* 瀏覽器有一個(gè)特點(diǎn):從WEB頁(yè)面產(chǎn)生的文件請(qǐng)求都會(huì)帶上COOKIE约郁;
如果是CORS跨域,客戶端AJAX請(qǐng)求必須設(shè)置withCredentials頭信息為true但两。
Token
Token是無(wú)狀態(tài)的(stateless)鬓梅。也就是說(shuō),服務(wù)端不需要在數(shù)據(jù)庫(kù)中存儲(chǔ)和Token相關(guān)的字段镜遣,Token本身就已經(jīng)包含了用戶的所有信息(生成Token的方式很多,其中比較著名的是JWTs: JSON Web Tokens)士袄。
客戶端一般在request header里面利用Authorization
頭傳遞Token值悲关,格式為Bearer {JWT}
(該格式并不是絕對(duì)的,要根據(jù)服務(wù)端具體情況來(lái)設(shè)置)娄柳。
Token有如下特征:
- Token值同樣需要服務(wù)端提供(通過(guò)API返回)
和Cookies不同寓辱,返回值不需要掛載在Set-Cookie
上,而是利用其它response header或者response body返回Token值赤拒; - 需要客戶端存儲(chǔ)
和Cookies不同秫筏,瀏覽器無(wú)法自動(dòng)在下一次請(qǐng)求中自動(dòng)掛載身份信息诱鞠。客戶端必須自行存儲(chǔ)Token值(建議用localstorage
)这敬,然后在后續(xù)請(qǐng)求中通過(guò)設(shè)置request header來(lái)傳遞Token信息航夺; - 無(wú)CSRF風(fēng)險(xiǎn)
- 適合移動(dòng)端身份認(rèn)證
- Token支持各類跨域
客戶端如何設(shè)置Token?代碼如下:
// JS
var res = new XMLHttpRequest();
...
req.setRequestHeader('Authorization',"Bearer " + token);
// JQuery
$.ajax({
url: api,
type: "GET",
headers: { "Authorization": "Bearer " + token}
})
小結(jié)
目前崔涂,大部分應(yīng)用還是用Cookies做身份驗(yàn)證(尤其是PC端)阳掐;移動(dòng)端HTML5頁(yè)面(Hybird App)API的權(quán)限驗(yàn)證,更多會(huì)采用Token冷蚂,并且走HTTPS協(xié)議缭保。