瀏覽器Cookie 為無狀態的Http協議帶來方便快速的解決方案,雖然太過依賴Cookie會產生潛在的風險,但用在一些不那麼需要注重安全的應用上還是非常適合,。
這篇文章會從認識cookie是什麼開始,到解說如何搭配cookie來製作商務網站常見的購物車。
大綱:
- Cookie是什麼?
- Client 端設計流程
- 存取Cookie
- 撰寫更友善的JS Cookie Setter/Getter
Cookie是什麼?
Cookie是瀏覽器的預設機制,提供4MB的空間去給網站暫存後續還會用到的資料,讓資料在其他頁面也能夠被取得,如果我們開啟開發者工具來看,就可以看到目前client所有的cookie:
Cookie預設在每次網站送出Request的時候,就會被跟著夾帶到Server,而Server回傳Response的時候,也會把Cookie一起帶下來到瀏覽器端,看一下瀏覽器發出Request時的Header就可以發現這件事情:(下圖是Facebooke發出請求時的內容)
也可以從server端設定cookie,方法是在Response裡面夾帶名為 Set-Cookie的Header:
Client 端設計流程
可以想見購物車資料被修改的時機是在使用者將商品加入購物車的那一刻,這時候我們只要把商品數量跟id紀錄起來就可以了,因為使用者還有可能會購買其他商品,所以還不需要太詳細的商品資料:
直到使用者進入購物車準備結帳時,就會需要跟後端調用商品確切價錢、確認有無優惠等動作:
由於cookie是會隨著送出的request一起到後端Server,因此我在後端可以直接拿到設定的cookie內容,然後去資料庫找到我要的相關資料,包成物件後再回傳到客戶端。
而直到使用者離開購物車頁面進入結帳頁面的最後一刻,我才會把剛剛使用者儲存的購物車資料存到Session,給訂單頁面的controller處理,避免使用者在結帳時發生商品資料與購買金額不一致的情形。
存取Cookie
cookie 文件: https://curl.haxx.se/rfc/cookie_spec.html
瀏覽器有提供api讓開發者使用js拿到cookie,直接使用document.cookie就可以拿到了:
拿到Cookie
document.cookie
設定cookie
設定cookie的方式並不是像操作js物件的Key/Value那麼直觀,而是要使用一定格式的字串"name=xxx" 但是後面會講到,可以利用js來包裝程簡潔好用function讓我們去設定它。
document.cookie = "name=thecontentIwanttosave; path=/; expires=Thu, 18 Feb 2019 12:00:00 GMT";
要注意設定cookie時一起設定的path值會影響你在該頁面可以存取的cookie。
那麼path又是什麼?path是cookie的選項設定之一,跟domain可以搭配,domain是告訴瀏覽器這個cookie只能在這個被設定的域名下面使用,以防止別的網站可以拿到我的機密資訊。
**Cookie path syntax : **
The path attribute is used to specify the subset of URLs in a domain for which the cookie is valid. If a cookie has already passed domain matching, then the pathname component of the URL is compared with the path attribute, and if there is a match, the cookie is considered valid and is sent along with the URL request. The path “/foo” would match “/foobar” and “/foo/bar.html”. The path “/” is the most general path.
撰寫更友善的JS Cookie Setter/Getter
當我跟瀏覽器拿到cookie的時候,可能拿到的東西是這樣一整個字串:
瀏覽器沒有提供key value存取,所以我們只能操作字串,既然cookie是用分號去分隔,那用js的split就可以解決:
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
parts.pop().split(";").shift();
但也不可能每次要拿個cookie都要操作字串,所以為了讓開發上能夠更順暢,我們可以把這段code包成function,減少重複的code。
這裡還有兩件事要注意:
- 空白字元在每個瀏覽器跟cookie的版本的表現可能都不一樣,因此以防萬一我們會將它轉為其他字元代替。
- 為了避免編碼問題,我們統一將cookie轉為URI編碼。
Getter
function setCookie(name,value){
value = encodeURIComponent(JSON.stringify(value).replaceAll(' ','+'))
document.cookie=`${name}=${value}; path=/;`
return getCookie(name)
}
Setter
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
let res
if (parts.length == 2){
res= parts.pop().split(";").shift();
return JSON.parse(decodeURIComponent(res).replaceAll('+',' '))
}else{
return undefined
}
}
做到這裡,就剩下畫面呈現跟功能操作了,你應該已經可以很順暢的開始開發購物車,如果有任何其他問題,非常樂意你聯絡我跟我討論:
Gmail : moojitsai@gmail.com