假設(shè)我有一個(gè)獲取驗(yàn)證碼的介面它在https://api.b.com/captcha下面。
在我的想像中驗(yàn)證碼刷新功能是透過(guò)在url後面加上?時(shí)間戳來(lái)實(shí)現(xiàn)的,例如把url變成這樣子
https://api.b.com/captcha?149...
傳統(tǒng)的驗(yàn)證碼應(yīng)該主要是透過(guò)session來(lái)做的吧,前端會(huì)在cookie裡面記錄一個(gè)session id。
後端也會(huì)在redis裡面記錄這個(gè)session id以及它對(duì)應(yīng)的驗(yàn)證碼。
前端有個(gè)點(diǎn)擊驗(yàn)證碼刷新的功能,每次點(diǎn)擊都會(huì)產(chǎn)生新的驗(yàn)證碼,每次都會(huì)在redis裡面更新這個(gè)session id對(duì)應(yīng)的驗(yàn)證碼的值。
驗(yàn)證方式是透過(guò)查詢r(jià)edis裡面的session id得值和前端的值是否一致來(lái)完成的。
現(xiàn)在,我在做一個(gè)前後端分離的專案。
然後有一個(gè)cookie跨域的問(wèn)題我不知道怎麼解決。
場(chǎng)景如下前端項(xiàng)目在 www.a.com的網(wǎng)域下,後端項(xiàng)目在 api.b.com的網(wǎng)域下。
前端和後端是在不同的域名下的(其實(shí)把兩個(gè)項(xiàng)目放在同一個(gè)域名下面也是可以的,學(xué)習(xí)目的就不這麼做了),於是cookie無(wú)法共享,換而言之我獲取不到session id了。那麼傳統(tǒng)的方式好像就不行了。
PS: 前端的伺服器會(huì)用nginx做,後端用的是spring-boot。
我想產(chǎn)生一個(gè)簡(jiǎn)單的token,token只包含了一個(gè)uuid,用來(lái)辨別使用者。我透過(guò)這個(gè)toekn的uuid和redis裡面的uuid比對(duì)來(lái)判斷驗(yàn)證碼的值是否正確。所以我將會(huì)回傳一個(gè)這樣子的結(jié)果
{
image : base64轉(zhuǎn)碼后的圖片,
token : uuid
}
關(guān)於為什麼發(fā)base64轉(zhuǎn)碼後的圖片,主要是因?yàn)榍岸说膇mg標(biāo)籤是支援base64的。發(fā)這個(gè)話直接顯示出來(lái)沒(méi)問(wèn)題(不是一個(gè)不考慮古老瀏覽器的項(xiàng)目)。
但是這樣子做,好像也不太合理。因?yàn)檫@樣子存取驗(yàn)證碼的位址的時(shí)候就不能看見(jiàn)驗(yàn)證碼的圖片了。不方便調(diào)試查看驗(yàn)證碼的樣式了,其實(shí)也不算特別不方便,只是還要特地寫個(gè)js來(lái)設(shè)定img的src,感覺(jué)挺蠢的。
把token放到response的header裡面。 js是唸得到response header裡面的東西的。然後這樣子驗(yàn)證碼的圖片也可以透過(guò)位址直接顯示出來(lái)。但是特喵的,感覺(jué)也很蠢。因?yàn)榫筒荒苡玫轿蚁胂裰械乃⑿买?yàn)證碼的方式了。直接簡(jiǎn)單的在後面加上時(shí)間戳記就修改的方式。
驗(yàn)證碼我不管了,前端的伺服器去做這事情吧,登陸的時(shí)候在前端伺服器驗(yàn)證驗(yàn)證碼,然後我後端只驗(yàn)證帳號(hào)密碼是不是正確的回個(gè)token算了。每次造訪其他的api帶上token就好了。
實(shí)在想不到怎麼做了,相關(guān)資料也沒(méi)找到(可能是我的搜尋方式有問(wèn)題),所以求各位大佬幫忙....
認(rèn)真的又查了下這個(gè)問(wèn)題應(yīng)該是單一登入的問(wèn)題吧?
你要解決的是跨域攜帶cookie的問(wèn)題。首先要確定你跨網(wǎng)域使用的是cors技術(shù),cors可以基於 HTTP cookies 和 HTTP 認(rèn)證資訊發(fā)送身分憑證。 透過(guò)XMLHttpRequest 的 withCredentials 標(biāo)誌設(shè)定為 true,從而向伺服器發(fā)送 Cookies。
var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';
function callOtherDomain(){
if(invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
}
除了前端發(fā)送請(qǐng)求要新增withCredential外,伺服器的回應(yīng)頭也需要加入Access-Control-Allow-Credentials: true
。另外,回應(yīng)頭不能設(shè)定 Access-Control-Allow-Origin 的值為“*”,必須設(shè)為具體的來(lái)源 http://foo.example。